MySQL: LOCK TABLES с автоматической фиксацией и START TRANSACTION - PullRequest
0 голосов
/ 26 мая 2018

В документации по 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 вместо НАЧАЛО СДЕЛКИ . Есть идеи? Спасибо

Ответы [ 2 ]

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

  • Для определенных приложений autocommit=ON - это нормально.

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

  • Do not useautocommit=OFF, слишком легко забыть сделать COMMIT.

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

0 голосов
/ 26 мая 2018

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, по моему мнению.Но это то, что задокументировано.

...