为啥 START TRANSACTION 不会隐式影响自动提交

Posted

技术标签:

【中文标题】为啥 START TRANSACTION 不会隐式影响自动提交【英文标题】:Why does START TRANSACTION doesn't affect on autocommit implicitly as it should为什么 START TRANSACTION 不会隐式影响自动提交 【发布时间】:2017-07-04 11:22:12 【问题描述】:

所以这是来自文档:

为单个系列隐式禁用自动提交模式 语句,使用START TRANSACTION 语句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

所以据我了解,不像使用BEGIN;不应将自动提交设置为 0 的命令,START TRANSACTION 应将其设置为 0。

现在如果我这样做(在我开始交易之后):

select @@autocommit;

我得到了 1 的值。

为什么即使我使用START TRANSACTION 命令仍然启用自动提交?我认为 autocommit 变量是单个会话的本地变量。或者即使它说 1,它实际上在事务中设置为 0,但无法通过运行 SELECT @@autocommit; 查询来获取该信息?

【问题讨论】:

【参考方案1】:

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

使用START TRANSACTION,自动提交保持禁用状态,直到您使用COMMITROLLBACK 结束事务。然后自动提交模式恢复到之前的状态。

autocommit 变量的值是 MySQL 存储“先前状态”的位置,以便在事务完成后它可以恢复到它。

您可以通过实验确认遵循此行为。在事务中进行更改,然后回滚事务。

CREATE TABLE test.MyTable (mycolumn TEXT);

START TRANSACTION;
INSERT INTO test.MyTable (mycolumn) VALUES ('Thing 1');
ROLLBACK;

SELECT * FROM test.MyTable; -- finds the row is gone

请注意,您所做的更改已回滚。如果自动提交已经生效,那么回滚将永远不会起作用,因为每条语句都会在执行后立即提交。

【讨论】:

是的,这是有道理的。我认为自动提交变量有不同的作用。但正如你所说,如果自动提交设置为 1,则无法回滚。20 小时冷却期过后将奖励赏金。【参考方案2】:

我建议@@autocommit 无关紧要。引擎知道它在一个事务中(STARTBEGIN),所以它忽略了autocommit 的设置。相反,它会一直等待更改直到COMMIT(或ROLLBACK)。

或者你有什么理由相信autocommit 的值是相关的? (除了SELECT @@autocommit。)

【讨论】:

我并没有真正意识到自动提交变量的作用。我虽然会通过执行Start transaction 之类的操作来更新每个会话,并在提交更改时更改为之前的值。 比尔说得比我好。

以上是关于为啥 START TRANSACTION 不会隐式影响自动提交的主要内容,如果未能解决你的问题,请参考以下文章

为啥 GCC 会警告这种隐式转换?

在 C# 中传递数组参数:为啥它是通过引用隐式传递的?

为啥隐式展开的可选选项不在 [String : Any] 类型的字典中展开

即使我有 session_start(); 我的会话变量也不会传递到我的其他页面;在所有 3 页的开头。为啥是这样?

MSSQL Transaction[事务] and Procedure[存储过程]

mysql:set autocommit=0与start transaction