MySQL:具有自动提交功能的LOCK TABLES与START TRANSACTION

时间:2018-05-26 06:02:30

标签: mysql transactions innodb autocommit

在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"和#34; START TRANSACTION",我真的不明白为什么要使用 autocommit 而不是 START TRANSACTION 。有任何想法吗?感谢

2 个答案:

答案 0 :(得分:6)

根据{{​​3}}

LOCK TABLES隐式提交交易

因此,如果您按照以下顺序执行操作,则不会执行您的操作:

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然后BEGIN开始交易?

https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html说:

  

开始事务(例如,使用START TRANSACTION)隐式提交任何当前事务并释放现有表锁。

这对我来说很奇怪。显式BEGIN(或START TRANSACTION)释放表锁,但事务的隐式启动不会?在我看来,这个功能充满了WTF。但这就是所记录的内容。

答案 1 :(得分:0)

  • 从不(好吧,我没有听说过案例)在InnoDB中使用 LOCK TABLES LOCK TABLES是一把大锤。它可能会严重降低您的系统速度。

  • 对于某些应用, autocommit=ON 没问题。

  • 对于某些应用,请使用 BEGINSTART TRANSACTION)和COMMIT - 让它们保持干净配对。

  • 使用 autocommit=OFF ,很容易忘记COMMIT

  • 请谨慎记住 DDL 语句COMMIT。 (直到MySQL 8.0。)