На этой странице описываются конкуренция за данные транзакций, сериализуемость и изоляция. Примеры кода для транзакций приведены в статье Транзакции и пакетная запись.
Транзакции и конкуренция за данные
Чтобы транзакция была успешной, документы, полученные в результате операций чтения, не должны изменяться операциями вне транзакции. Если другая операция попытается изменить один из этих документов, она вступит в состояние конкуренции за данные с транзакцией.
- Конкуренция за данные
- Когда две или более операции конкурируют за управление одним и тем же документом. Например, одной транзакции может потребоваться, чтобы документ оставался согласованным, в то время как параллельная операция пытается обновить значения полей этого документа.
Cloud Firestore разрешает конфликт данных, задерживая или отменяя одну из операций. Клиентские библиотеки Cloud Firestore автоматически повторяют транзакции, которые не удалось выполнить из-за конфликта данных. После определенного количества попыток транзакция завершается неудачно и возвращается сообщение об ошибке:
ABORTED: Too much contention on these documents. Please try again.
Решение о том, какую операцию отменить или отложить, зависит от типа управления параллелизмом.
Управление параллелизмом
Режим параллелизма – это настраиваемый параметр базы данных. Cloud Firestore поддерживает следующие режимы параллелизма:
PESSIMISTIC: пессимистичное управление параллелизмом предполагает, что конкуренция за данные вероятна. В пессимистических транзакциях используются блокировки базы данных, чтобы другие операции не могли изменить данные.При пессимистичном управлении параллелизмом транзакции блокируют документы, которые они читают. Блокировка документа транзакцией не позволяет другим транзакциям, пакетным записям и записям, не связанным с транзакциями, изменять этот документ. Транзакция снимает блокировку документов во время фиксации. Она также снимает блокировки, если истекает время ожидания или происходит сбой.
Когда транзакция блокирует документ, другие операции записи должны дождаться, пока транзакция снимет блокировку. Транзакции получают блокировки в хронологическом порядке.
OPTIMISTIC: Оптимистичное управление параллелизмом предполагает, что конкуренция за данные маловероятна или что удерживать блокировки базы данных неэффективно. Оптимистичные транзакции не используют блокировки базы данных, чтобы запретить другим операциям изменять данные.При оптимистичном управлении параллелизмом транзакция отслеживает все документы, которые вы читаете в рамках транзакции. Транзакция завершает операции записи, только если ни один из этих документов не был изменен во время ее выполнения. Если какой-либо документ изменился, обработчик транзакции повторит транзакцию. Если после нескольких попыток транзакция не может получить чистый результат, она завершается неудачно из-за конфликта данных.
Режимы параллельной работы по умолчанию
Для версии Standard по умолчанию установлено значение PESSIMISTIC. Значение по умолчанию для версии Enterprise – OPTIMISTIC. Однако поведение также зависит от типа клиентской библиотеки:
- В SDK для мобильных устройств и веб-приложений используется оптимистичное управление параллелизмом. SDK для мобильных устройств и веб-приложений работают независимо от этой настройки, поскольку они всегда эмулируют оптимистичный параллелизм.
- Клиентские библиотеки сервера используют управление параллелизмом, заданное в настройках базы данных.
Режим параллельного просмотра
Чтобы посмотреть режим параллелизма на стороне сервера, выполните команду gcloud firestore databases describe.
gcloud firestore databases describe \
--project=PROJECT_ID \
--database=DATABASE_ID
Как изменить режим параллельной работы
Выполните команду gcloud firestore databases update, чтобы изменить режим параллельной обработки на стороне сервера для базы данных.
gcloud firestore databases update \
--project=PROJECT_ID \
--database=DATABASE_ID \
--concurrency-mode=CONCURRENCY_MODE
Значения:
- CONCURRENCY_MODE – это
PESSIMISTICилиOPTIMISTIC. - PROJECT_ID – идентификатор проекта Google Cloud.
- DATABASE_ID – идентификатор базы данных Cloud Firestore.
Конкуренция за данные в SDK для мобильных устройств и веб-приложений
SDK для мобильных устройств и веб-приложений эмулируют транзакции оптимистичного параллелизма, используя предварительные условия записи в версиях документов. Это происходит независимо от режима параллелизма базы данных. В SDK для мобильных устройств и веб-приложений не используется функция встроенных транзакций, поэтому даже если для режима параллельной работы базы данных задано значение PESSIMISTIC, мобильные клиенты по-прежнему будут работать в оптимистичном режиме.
В SDK для мобильных устройств и веб-приложений используется оптимистичное управление параллелизмом, поскольку они могут работать в средах с высокой задержкой и ненадежным сетевым подключением. Блокировка документов в среде с высокой задержкой приведет к слишком большому количеству сбоев из-за конфликтов данных.
Конкуренция за данные в клиентских библиотеках сервера
Серверные клиентские библиотеки (C#, Go, Java, Node.js, PHP, Python, Ruby) используют функцию встроенных транзакций. В этих транзакциях используется настройка режима параллелизма на уровне базы данных, а значение по умолчанию зависит от версии:
В версии Enterprise по умолчанию используется оптимистичное управление параллелизмом, чтобы поддерживать операции, которые сканируют целые коллекции. Оптимистичное управление параллелизмом помогает избежать операций сканирования, которые блокируют большое количество документов.
В стандартной версии используется пессимистичное управление параллелизмом и предполагается низкая задержка и надежное подключение к базе данных.
Упорядочиваемая изоляция
Конкуренция за данные между транзакциями тесно связана с уровнями изоляции базы данных. Уровень изоляции базы данных описывает, насколько хорошо система справляется с конфликтами между параллельными операциями. Конфликт возникает из-за следующих требований к базе данных:
- Для транзакций требуются точные и согласованные данные.
- Для эффективного использования ресурсов базы данных выполняют операции параллельно.
В системах с низким уровнем изоляции операция чтения в рамках транзакции может считывать неточные данные из незафиксированных изменений в параллельной операции.
Сериализуемая изоляция определяет самый высокий уровень изоляции. Сериализуемая изоляция означает, что:
- Вы можете предположить, что база данных выполняет транзакции последовательно.
- На транзакции не влияют незафиксированные изменения в параллельных операциях.
Это условие должно выполняться, даже если база данных выполняет несколько транзакций параллельно. База данных должна реализовывать управление параллелизмом для разрешения конфликтов, которые могут нарушить эту гарантию.
Cloud Firestore гарантирует сериализуемую изоляцию транзакций. Транзакции в Cloud Firestore сериализуются и изолируются по времени фиксации.
Сериализуемая изоляция по времени фиксации
Cloud Firestore присваивает каждой транзакции время фиксации, которое представляет собой единую точку во времени. Когда Cloud Firestore фиксирует изменения транзакции в базе данных, можно считать, что все операции чтения и записи в рамках транзакции происходят точно в момент фиксации.
Фактическое выполнение транзакции занимает некоторое время. Выполнение транзакции начинается до времени фиксации, и выполнение нескольких операций может перекрываться. Cloud Firestore поддерживает сериализуемую изоляцию и гарантирует, что:
- Cloud Firestore фиксирует транзакции в порядке времени фиксации.
- Cloud Firestore изолирует транзакции от параллельных операций с более поздним временем фиксации.
В случае конфликта данных между параллельными операциями Cloud Firestore использует оптимистичное и пессимистичное управление параллелизмом для разрешения конфликта.
Изоляция в рамках транзакции
Изоляция транзакций также применяется к операциям записи в рамках транзакции. Запросы и операции чтения в транзакции не видят результаты предыдущих операций записи в этой транзакции. Даже если вы измените или удалите документ в рамках транзакции, все операции чтения документов в этой транзакции вернут версию документа на момент фиксации, до операций записи транзакции. Если документ не существовал на указанный момент времени, операции чтения ничего не возвращают.
Проблемы с конфликтами данных
Дополнительную информацию о конфликтах данных и способах их устранения можно найти на странице устранения неполадок.