LOCK TABLES
неявно фиксирует транзакцию в соответствии с https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
Так что, если бы вы выполнили следующую последовательность, она бы не сделала то, что вы намеревались:
BEGIN;
/* I think I'm in transaction 1 */
LOCK TABLES ...;
/* but that implicitly committed transaction 1 */
UPDATE blab blah ...;
/* I think I'm still in transaction 1, but this update caused
a new transaction 2 to begin and autocommit */
UPDATE yadda yadda ...;
/* I think I'm still in transaction 1, but this update caused
a new transaction 3 to begin and autocommit */
COMMIT;
смысл использования транзакций - это когда вам нужно запустить несколько обновлений, но вы хотите, чтобы результат всех обновлений фиксировался вместе или не выполнялся вообще.
Приведенный выше пример не фиксирует два обновления вместе атомарно.Каждый из них имеет свою собственную транзакцию с автоматическим подтверждением.Поэтому один может преуспеть, а другой нет.
Рекомендуется сделать следующее:
SET autocommit=0;
LOCK TABLES ...;
/* that implicitly committed any outstanding transaction, but that's OK */
UPDATE blab blah ...;
/* because autocommit=0, a new DML statement implicitly starts a new transaction */
UPDATE yadda yadda ...;
/* the new transaction is still open */
COMMIT;
UNLOCK TABLES;
Это фиксирует оба обновления вместе, атомарно.
Почему бы не просто LOCK TABLES, а затем НАЧАТЬ начать транзакцию?
https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html говорит:
Начало транзакции (например, с START TRANSACTION) неявно фиксирует любую текущую транзакцию и освобождает существующие блокировки таблиц.
Это кажется странным для меня.Явный BEGIN (или START TRANSACTION) снимает блокировку таблицы, но неявный запуск транзакции - нет?Эта особенность полна WTF, по моему мнению.Но это то, что задокументировано.