Чтение объекта хранилища данных (keys_only) внутри транзакций ndb

#google-app-engine #google-cloud-platform #google-cloud-datastore #app-engine-ndb

#google-app-engine #google-облачная платформа #google-cloud-хранилище данных #app-engine-ndb

Вопрос:

У меня есть вопрос, касающийся чтения объекта хранилища данных внутри транзакции ndb.

Я знаю, что когда мы читаем объект внутри транзакции ndb, этот конкретный объект блокируется, и никакой другой поток не может поместить / обновить / записать тот же объект, потому что это приведет к ошибке конкуренции. Это полностью имеет смысл.

Однако, что происходит, когда мы читаем только ключ объекта вместо всего объекта внутри транзакции? Это можно сделать, передав флаг keys_only как True в ndb.query().fetch() В этом случае объект снова будет заблокирован?

Ответ №1:

Документация хранилища данных для блокировок транзакций гласит:

Транзакции чтения-записи используют блокировки чтения / записи для обеспечения изоляции и сериализации.

И в нем не упоминается ни о какой ситуации со спецификой использования keys_only во время транзакций. Поэтому я бы предположил, что то же самое относится и к этой ситуации, что имеет смысл, если учесть, что вы все еще выполняете чтение, тем не менее, вы просто игнорируете данные.

При этом, возможно, это то, что можно было бы улучшить в хранилище данных или даже прояснить в документации. Если вы хотите, вы можете рассмотреть возможность открытия запроса функции для Google, чтобы реализовать это, перейдя по этой ссылке .

Ответ №2:

В общем, лучше думать о транзакциях с точки зрения их гарантии — сериализуемости, а не деталей их реализации — в данном случае блокировок чтения / записи. Детали реализации (как выполняются запросы, детализация блокировки, что именно блокируется и т. Д.) Потенциально Могут измениться в любое время, В то время как гарантия не изменится.

Для этого конкретного вопроса и при условии текущей реализации Firestore в режиме хранилища данных: чтобы обеспечить сериализуемость, запрос только для ключей в транзакции T1 блокирует диапазоны записей индекса, проверенных запросом. Если такой запрос вернул ключ K для сущности E, то попытка удалить E в другой транзакции T2 должна удалить все записи индекса E, включая ту, которая находится в диапазоне, заблокированном запросом. Итак, в этом примере T1 и T2 требуют одинаковых блокировок, и одна из двух транзакций будет отложена или прервана.

Обратите внимание, что существуют другие способы, позволяющие T2 конфликтовать с T1: это также может быть создание новой сущности, которая будет соответствовать запросу T1 (что потребует записи записи индекса в диапазоне, заблокированном запросом T1).

Наконец, если бы T2 обновлял (а не удалял) E таким образом, чтобы требовались какие-либо обновления для записей индекса в диапазоне, проверяемом запросом T1 (например, если запрос представляет собой что-то вроде ‘select * from X where a = 5’, и обновление до E не изменяет значение его свойства ‘a’), тогда T1 иT2 не будет конфликтовать (это оптимизация — поведение все равно было бы правильным, если бы эти две транзакции конфликтовали, и фактически для баз данных «собственного хранилища данных» они могут конфликтовать).