mysql:用autocommit和start transaction锁定表

mo49yndu  于 2021-06-23  发布在  Mysql
关注(0)|答案(2)|浏览(341)

在mysql文档中,有一句话我不明白:
将锁表和解锁表与事务表(如innodb表)一起使用的正确方法是,先将autocommit=0(not start transaction)设置为紧跟着锁表开始事务,然后在显式提交事务之前不调用解锁表(https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html)
即使在文档中搜索了很多,研究了“autocommit”和“start transaction”的描述,我真的不明白为什么用autocommit代替start transaction。有什么想法吗?谢谢

7xllpg7q

7xllpg7q1#

从来没有(嗯,我没听说过)使用 LOCK TABLES 与innodb合作。 LOCK TABLES 是一把大锤。它可能会严重减慢你的系统。
对于某些应用程序, autocommit=ON 很好。
对于某些应用程序,请使用 BEGIN ( START TRANSACTION )以及 COMMIT --保持它们整齐地配对。
不要使用 autocommit=OFF ,太容易忘记去做 COMMIT .
记住ddl语句 COMMIT . (直到mysql 8.0。)

pzfprimi

pzfprimi2#

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事务)释放表锁,而隐式的事务启动不释放表锁?在我看来,这个功能充满了wtf。但这是有记载的。

相关问题