Потеря обновления относится к ситуации, когда два одновременных обновления выполняются одновременно, и последнее обновление покрывает предыдущее обновление.Потеря обновления вызвана отсутствием гарантированной согласованности данных. Возьмите каштан:
- У пользователя А на банковской карте 100 юаней, в определенный момент пользователь Б переводит А 50 юаней (операция Б), и в то же время пользователь С переводит 50 юаней А (операция С);
- B операция из базы данных
读取
Его текущий баланс равен 100, а новый баланс рассчитывается как 100+50=150. - Операции C также извлекаются из базы данных.
读取
Его текущий баланс равен 100, а новый баланс рассчитывается как 100+50=150. - Операция B будет балансировать = 150
写入
база данных, то операция C также будет balance=150写入
база данных - Окончательный баланс А становится 150
В приведенном выше примере А получает два перевода по 50 юаней одновременно, и окончательный баланс должен быть 200 юаней, но он становится 150 юаней из-за проблемы параллелизма.Причина в том, что, когда B и C инициируют запросы на перевод к A , две транзакции открываются одновременно.В сеансе базы данных выполняются две транзакции, и последняя транзакция получает данные промежуточного состояния предыдущей транзакции, что приводит к потере обновлений. Есть два распространенных решения:
- блокировать синхронное выполнение
- Проверяйте согласованность данных перед обновлением
пессимистический замок
Как следует из названия, пессимистичные блокировки будут думать, что кто-то другой изменит их при чтении данных, поэтому при выборке данных к текущим данным будет добавлена блокировка, и другим операциям не будет позволено изменяться, пока операция не завершится. Следует отметить, что как пессимистичные блокировки, так и оптимистичные блокировки являются определениями уровней бизнес-логики, и разные конструкции могут иметь разные реализации. Обычно используемая реализация пессимистической блокировки на уровне MySQL заключается в добавлении монопольной блокировки.
эксклюзивный замок
Глядя на информацию, можно найти множество объяснений эксклюзивных блокировок: «Эксклюзивные блокировки используются в транзакцияхselect xx for update
Заявление для достижения монопольной блокировки добавит блокировку на уровне строки к текущей строке, прежде чем текущая транзакция будет зафиксирована, другие транзакции не могут выполнить операцию обновления. "
Однако это не так, по сути это данные с монопольной блокировкой, другие транзакции не могут заблокировать данные, пока блокировка не будет снята (транзакция не завершится).
Причина, по которой эксклюзивные блокировки могут препятствовать обновлению, удалению и другим операциям, заключается в том, что операции обновления и удаления автоматически добавляют эксклюзивные блокировки.
То есть, даже если добавлена монопольная блокировка, операция выбора не может быть заблокирована. Синтаксис select XX for update может добавить монопольную блокировку к операции select. Таким образом, чтобы предотвратить потерю обновлений, вы можете добавить блокировку обновления при выборе, чтобы вы могли предотвратить выбор для обновления других транзакций (но обратите внимание, что вы не можете предотвратить выбор), например:
begin;
select * from account where id = 1 for update;
update account set balance=150 where id =1;
commit;
Таким образом, до отправки операции B операция C не может получить монопольную блокировку, тем самым избегая потери обновления, вызванной повторным обновлением учетной записи.
оптимистическая блокировка
Оптимистичная блокировка означает отсутствие блокировки при получении данных, оптимистичная — отсутствие конфликта в операции, а затем проверка конфликта при обновлении. пример:
begin;
select balance from account where id=1;
-- 得到balance=100;然后计算balance=100+50=150
update account set balance = 150 where id=1 and balance = 100;
commit;
Как и выше, если sql обнаруживает, что затронутое обновление равно 0 в процессе выполнения, это означает, что баланс не равен 100, то есть данные были изменены другими транзакциями.В это время бизнес может вернуться к сбой или повторный выбор и перерасчет