MySQL: LOCK TABLES с автоматической фиксацией и START TRANSACTION

В документации по MySQL есть утверждение, которое я не понимаю:

Правильный способ использования LOCK TABLES и UNLOCK TABLES с транзакционными таблицами, такими как таблицы InnoDB, состоит в том, чтобы начать транзакцию с SET autocommit = 0 (не START TRANSACTION), за которым следует LOCK TABLES, и не вызывать UNLOCK TABLES, пока вы не подтвердите транзакцию. в явном виде. ( https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html)

Даже после долгих поисков в документации и изучения описания "autocommit" и "START TRANSACTION", я действительно не понимаю, зачем использовать autocommit вместо START TRANSACTION. Есть идеи? Спасибо

2 ответа

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;

Это фиксирует оба обновления вместе, атомарно.

Почему бы просто не ЗАБЛОКИРОВАТЬ СТОЛЫ, а затем НАЧАТЬ начать транзакцию?

https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html говорит:

Начало транзакции (например, с помощью START TRANSACTION) неявно фиксирует любую текущую транзакцию и освобождает существующие блокировки таблиц.

Это кажется странным для меня. Явный BEGIN (или START TRANSACTION) снимает блокировку таблицы, но неявный запуск транзакции - нет? Эта особенность полна WTF, по моему мнению. Но это то, что задокументировано.

  • Никогда (ну, я не слышал о случае) использовать LOCK TABLES с InnoDB. LOCK TABLES это кувалда. Это может серьезно замедлить вашу систему.

  • Для определенных приложений autocommit=ON Это хорошо.

  • Для определенных приложений используйте BEGIN ( START TRANSACTION) а также COMMIT - Держите их в чистоте в паре.

  • Не использовать autocommit=OFF, это слишком легко забыть сделать COMMIT,

  • Помните, что операторы DDL неявно COMMIT, (До MySQL 8.0.)

Другие вопросы по тегам