В чем точная разница между двумя блокирующими предложениями чтения:
SELECT ... FOR UPDATE
а также
SELECT ... LOCK IN SHARE MODE
И зачем вам нужно использовать один над другим?
В чем точная разница между двумя блокирующими предложениями чтения:
SELECT ... FOR UPDATE
а также
SELECT ... LOCK IN SHARE MODE
И зачем вам нужно использовать один над другим?
Я пытался понять разницу между ними. Я задокументирую то, что нашел, в надежде, что это будет полезно следующему человеку.
И LOCK IN SHARE MODE
, и FOR UPDATE
гарантируют, что никакая другая транзакция не сможет обновить выбранные строки. Разница между ними заключается в том, как они обрабатывают блокировки при чтении данных.
LOCK IN SHARE MODE
не препятствует тому, чтобы другая транзакция читала ту же заблокированную строку.
FOR UPDATE
предотвращает другие блокирующие операции чтения той же строки (неблокирующие операции чтения по-прежнему могут читать эту строку; LOCK IN SHARE MODE
и FOR UPDATE
являются блокирующими операциями чтения).
Это имеет значение в таких случаях, как обновление счетчиков, когда вы считываете значение в одном выражении и обновляете значение в другом. Здесь использование LOCK IN SHARE MODE
позволит 2 транзакциям прочитать одно и то же начальное значение. Таким образом, если счетчик был увеличен на 1 обеими транзакциями, конечный счетчик может увеличиться только на 1, поскольку обе транзакции изначально считывают одно и то же значение.
Использование FOR UPDATE
заблокировало бы вторую транзакцию от чтения значения до завершения первой. Это обеспечит увеличение счетчика на 2.
Для обновления --- Вы сообщаете Mysql, что выбранные строки могут быть обновлены на следующих шагах (до окончания этой транзакции), так что mysql не предоставляет никаких блокировок чтения для одного и того же набора строк любым другим транзакция в этот момент. Другая транзакция (для чтения/записи) должна дождаться завершения первой транзакции.
For Share — указывает Mysql, что вы выбираете строки из таблицы только для чтения, а не для изменения до конца транзакции. Любое количество транзакций может получить доступ к блокировке чтения строк.
Примечание. Есть вероятность возникновения тупиковой ситуации, если этот оператор (для обновления, для общего доступа) используется неправильно.
В любом случае целостность ваших данных будет гарантирована, вопрос лишь в том, как база данных это гарантирует. Делает ли это это, вызывая ошибки времени выполнения, когда транзакции конфликтуют друг с другом (например, FOR SHARE), или делает это путем сериализации любых транзакций, которые могут конфликтовать друг с другом (например, FOR UPDATE)?
FOR SHARE (также известный как LOCK IN SHARE MODE): Транзакции сталкиваются с более высокой вероятностью сбоя из-за взаимоблокировки, поскольку они откладывают блокировку до момента получения оператора обновления (в этот момент они либо блокируются до тех пор, пока не будут сняты все блокировки чтения, либо завершаются ошибкой из-за блокировки). тупик, если выполняется другая запись). Тем не менее, только один клиент блокируется и в конечном итоге завершается успешно: другие клиенты потерпят тупик, если попытаются обновиться, поэтому только один из них добьется успеха, а остальным придется повторить свои транзакции.
ДЛЯ ОБНОВЛЕНИЯ: Транзакции не будут завершаться сбоем из-за взаимоблокировки, поскольку им не будет разрешено выполняться одновременно. Это может быть желательно, например, потому что упрощается рассмотрение многопоточности, если все обновления сериализуются для всех клиентов. Однако это ограничивает параллелизм, которого вы можете достичь, поскольку все остальные транзакции блокируются до тех пор, пока первая транзакция не будет завершена.
Профессиональный совет: в качестве упражнения я рекомендую потратить некоторое время, чтобы поиграть с локальной тестовой базой данных и парой клиентов mysql в командной строке, чтобы проверить это поведение для себя. Вот как я в конце концов сам понял разницу, потому что она может быть очень абстрактной, пока вы не увидите ее в действии.