SET autocommit = 1和mysql中的START TRANSACTION之间的区别(我错过了什么吗?)


78

我正在阅读MySQL中的事务,并且不确定是否正确掌握了某些特定内容,并且想确保我理解正确,所以请继续。我知道事务应该做什么,只是不确定我是否理解语句的语义。

因此,我的问题是,以下内容是否有错((如果是这种情况,错了)):

默认情况下,MySQL中启用了自动提交模式。

现在,SET autocommit=0;将开始事务,SET autocommit=1;将隐式提交。这是可能的COMMIT;,以及ROLLBACK;,在两个自动提交仍设置为0之后(和一个新的隐式启动事务)的情况下。

START TRANSACTION;基本上会SET autocommit=0;一直到COMMIT;ROLLBACK;发生。

换句话说,START TRANSACTION;SET autocommit=0;是等效的,除了以下事实:START TRANSACTION;等效地隐式添加了SET autocommit=0;afterCOMMIT;ROLLBACK;

如果是这种情况,我不理解http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_serializable-认为具有隔离级别意味着存在事务,意味着应始终关闭自动提交功能?

并且,如果在开始事务和设置自动提交之间还有另一个差异(上述差异除外),那是什么?

Answers:


79

了解数据库的事务(自动提交,显式和隐式)处理可以使您不必从备份还原数据。

事务控制数据操作语句以确保它们是原子的。“原子性”表示交易已发生或未发生。向数据库发出事务完成信号的唯一方法是使用COMMITorROLLBACK语句(根据ANSI-92,遗憾的是它不包含用于创建/开始事务的语法,因此它是特定于供应商的)。 COMMIT应用在交易中进行的更改(如果有)。ROLLBACK忽略事务中发生的任何动作-当UPDATE / DELETE语句做意外的事情时,这是非常理想的

通常,单个DML(插入,更新,删除)语句在自动提交事务中执行-语句成功完成后便会提交它们。这意味着在像您这样的情况下,没有机会将数据库回滚到语句运行之前的状态。当出现问题时,唯一可用的还原选项是从备份中重建数据(假设存在备份)。在MySQL中,默认情况下,InnoDB的自动提交功能为打开-MyISAM不支持事务。可以使用以下命令禁用它:

SET autocommit = 0

显式事务是指将语句包装在显式定义的事务代码块中-对于MySQL,即START TRANSACTION。它还需要在交易结束时明确做出COMMITROLLBACK声明。嵌套事务不在本主题范围内。

隐式交易与显式交易略有不同。隐式事务不需要显式定义事务。但是,像显式事务一样,它们需要提供COMMITorROLLBACK语句。

结论

显式事务是最理想的解决方案-它们需要语句COMMITROLLBACK来完成事务,并且明确说明正在发生的情况,以便其他人在需要时阅读。如果以交互方式使用数据库,则隐式事务是可以的,但是COMMIT只有在测试了结果并确定其有效之后,才应指定语句。

这意味着您应该使用:

SET autocommit = 0;

START TRANSACTION;
  UPDATE ...;

...并且仅COMMIT;在结果正确时使用。

也就是说,UPDATE和DELETE语句通常仅返回受影响的行数,而不返回特定的详细信息。将此类语句转换为SELECT语句,并尝试UPDATE / DELETE语句之前检查结果以确保正确性。

附录

DDL(数据定义语言)语句是自动提交的-它们不需要COMMIT语句。IE:表,索引,存储过程,数据库以及视图创建或更改语句。


9
哇,那太快了:-)非常感谢!我不太了解的是为什么我需要设置autocommit = 0; 在上面的示例中;并不意味着开始交易吗?如果没有,有什么区别?
ralokt 2010年

1
@tkolar:禁用自动提交会强制所有人使用START TRANSACTION;不是每个人都知道他们应该使用它。“当然,另一个DBA可能也会重新将其打开...
OMG Ponies,2010年

3
我想拥有SET autocommit = 0;一个是不要忘记使用交易的偏好
Timo Huovinen 2013年

因此,当我通过明确启动事务时START TRANSACTION,我还必须明确指定COMMIT即使autocommit为ON。是吗?
tomwang1013

在嵌套的存储过程Call中。我应该使用@OMGPonies
selvakumar

20

InnoDB中,您拥有START TRANSACTION;,它是此引擎中官方推荐的事务处理方式,而不是SET AUTOCOMMIT = 0;(除非SET AUTOCOMMIT = 0;InnoDB中用于事务,否则它不用于优化只读事务)。提交COMMIT;

您可能要SET AUTOCOMMIT = 0;InnoDB中用于测试目的,而不是精确地用于事务。

MyISAM中,您没有START TRANSACTION;。在此引擎中,SET AUTOCOMMIT = 0;用于交易。用COMMIT;或提交SET AUTOCOMMIT = 1;(以下MyISAM示例注释中解释的差异)。您也可以在InnoDB中以这种方式进行事务。

资料来源:http : //dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_autocommit

通用交易示例:

/* InnoDB */
START TRANSACTION;

INSERT INTO table_name (table_field) VALUES ('foo');
INSERT INTO table_name (table_field) VALUES ('bar');

COMMIT; /* SET AUTOCOMMIT = 1 might not set AUTOCOMMIT to its previous state */

/* MyISAM */
SET AUTOCOMMIT = 0;

INSERT INTO table_name (table_field) VALUES ('foo');
INSERT INTO table_name (table_field) VALUES ('bar');

SET AUTOCOMMIT = 1; /* COMMIT statement instead would not restore AUTOCOMMIT to 1 */

1

https://dev.mysql.com/doc/refman/8.0/zh-CN/lock-tables.html

将LOCK TABLES和UNLOCK TABLES与事务表(例如InnoDB表)一起使用的正确方法是,先以SET autocommit = 0(不是START TRANSACTION)后跟LOCK TABLES开始事务,并且在提交事务之前不要调用UNLOCK TABLES明确地。例如,如果您需要写入表t1并从表t2中读取,则可以执行以下操作:

SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;

有人知道为什么表锁只能用于autocommit=0但不能使用START TRANSACTION吗?在我看来,这完全是武断的。有技术原因吗?
jlh

1

如果您要使用回滚,请使用开始事务 ,否则请忘记所有这些内容,

默认情况下,MySQL自动将更改提交到数据库。

要强制MySQL不自动提交这些更改,请执行以下操作:

SET autocommit = 0;
//OR    
SET autocommit = OFF

要显式启用自动提交模式:

SET autocommit = 1;
//OR    
SET autocommit = ON;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.