предисловие
При бэкенд-разработке мы неизбежно столкнемся с одновременным обновлением данных MySQL.Как бэкенд-разработчик, мы должны знать, как решать такие проблемы, и это также часть знаний, которую часто рассматривают на собеседованиях.
Будет ли ОБНОВЛЕНИЕ заблокировано?
Если оператор SQL выглядит следующим образом, будет ли он заблокирован?
UPDATE table1 SET num = num + 1 WHERE id=1;
ответ - нет
MySQL на самом деле поддерживает строки блокировки (InnoDB), и когда операции обновления / удаления, такие как «Добавить строки», это автоматически блокируется. ТолькоНет, пока не будет ключевого слова UPDATE с полной блокировкой., для приведенного выше оператора MySQL это не просто оператор UPDATE, он должен быть похож на два оператора SQL (псевдокод):
a = SELECT * FROM table1 WHERE id=1;
UPDATE table1 SET num = a.num + 1 WHERE id=1;
Блокировки при выполнении оператора SELECT нет, только при выполнении UPDATE. Поэтому возникают несоответствия в обновленных данных во время параллельных операций. Причина найдена, и решение проблемы не за горами. Есть два решения этой проблемы:
- Явно заблокировать SELECT через транзакцию
- Используйте оптимистическую блокировку
ВЫБЕРИТЕ явную блокировку
SELECT ... LOCK IN SHARE MODE #共享锁,其它事务可读,不可更新
SELECT ... FOR UPDATE #排它锁,其它事务不可读写
SET AUTOCOMMIT=0;
BEGIN WORK;
a = SELECT num FROM table1 WHERE id=2 FOR UPDATE;
UPDATE table1 SET num = a.num + 1 WHERE id=2;
COMMIT WORK;
Используйте оптимистическую блокировку
Когда данные специально обновляются, информация о номере версии будет добавлена к условиям обновления.
- Если номер версии не изменился, это означает, что строка данных не обновлялась, а также соответствует условиям обновления, поэтому обновление пройдет успешно.
- Когда номер версии изменяется, строка данных не может быть обновлена, поскольку условие не выполняется, и в это время необходимо выполнить операцию SQL. (повторно запросите строку данных и снова обновите данные с новым номером версии)
упражняться
Попрактикуйтесь в блокировке обновлений
Студенческая таблица с фрагментом данных
Откройте два клиента
select name from student where id = 1 for update;
резюме
Как правило, эти два метода могут поддерживать параллельные операции обновления базы данных. Однако то, какой из них использовать, зависит от фактического сценария приложения, который лучше поддерживается сценарием приложения и оказывает наименьшее влияние на производительность.
Ссылка из: