<p>autocommit</p><p>一、概念</p><p>事务自动提交设置,默认为1,即除非显示声明一个事务的开始,否则每一个查询都会被当做独立的事务被处理</p><p>默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务</p><p>关闭自动提交的原因,事务作为一个独立处理最小单元,往往需要处理一系列连续的数据操作,这些操作被视为一个整体,需要同时成功或同时失败,而不能其中某个操作成功;比如:A汇款给B,B接收到歀;即 A的账户扣款,而B的账户增加;必须同时成功或同时失败;如果成功则commit否则整体回滚;批量数据提交,如果提交1000条数据操作,需要处理1000次提交commit,而如果关闭autocommit等1000条数据处理完毕后统一一次提交</p><p>存储引擎需支持事务,如InnoDB,而MyISAM不支持事务</p><p>事务是否开启:如果没有显示的开启事务,autocommit 才会生效;</p><p>// 示例</p><p>// descrpiton:在显示开启事务的情况下,无论是否开启自动提交,下面示例均会发生</p><p>// 结论:在显示开启事务的情况下,autocommit 不生效</p><pre class="brush:sql;toolbar:false">//console1
mysql>begin;
QueryOK,0rowsaffected
mysql>select*fromt_order;
+----+-------+--------------+--------+
|id|name|order_no|status|
+----+-------+--------------+--------+
|1|订单1|DD_000000001|1|
|2|订单2|DD_000000002|2|
|3|订单3|DD_000000003|3|
+----+-------+--------------+--------+
mysql>updatet_ordersetorder_no="DD_000000033"whereid=3;
QueryOK,1rowaffected
mysql>select*fromt_order;//修改结果当前会话中的当前事务可见
+----+-------+--------------+--------+
|id|name|order_no|status|
+----+-------+--------------+--------+
|1|订单1|DD_000000001|1|
|2|订单2|DD_000000002|2|
|3|订单3|DD_000000033|3|
+----+-------+--------------+--------+
3rowsinset</pre><pre class="brush:sql;toolbar:false">//console2
mysql>select*fromt_order;//不可见
+----+-------+--------------+--------+
|id|name|order_no|status|
+----+-------+--------------+--------+
|1|订单1|DD_000000001|1|
|2|订单2|DD_000000002|2|
|3|订单3|DD_000000003|3|
+----+-------+--------------+--------+</pre><p>3 rows in set</p><pre class="brush:sql;toolbar:false">//console1
mysql>commit;
QueryOK,0rowsaffected
//console2
mysql>select*fromt_order;
+----+-------+--------------+--------+
|id|name|order_no|status|
+----+-------+--------------+--------+
|1|订单1|DD_000000001|1|
|2|订单2|DD_000000002|2|
|3|订单3|DD_000000033|3|
+----+-------+--------------+--------+
3rowsinset</pre><p>二、基本操作</p><pre class="brush:sql;toolbar:false">//查询
mysql>SELECT@@autocommit;
+--------------+
|@@autocommit|
+--------------+
|1|
+--------------+
1rowinset
mysql>SHOWVARIABLESLIKE"%AUTOCOMMIT%";
+---------------+-------+
|Variable_name|Value|
+---------------+-------+
|autocommit|ON|
+---------------+-------+
1rowinset
//修改
mysql>SETautocommit=0;
QueryOK,0rowsaffected
//在当前session关闭autocommit:
mysql>set@@session.autocommit=0;
QueryOK,0rowsaffected(0.00sec)
//在global级别关闭autocommit:
mysql>set@@global.autocommit=0;
QueryOK,0rowsaffected(0.01sec)</pre><p>三、产生的问题</p><p>示例:</p><p>// 系统准备</p><p>// MySQL:Server version: 5.7.17 ;</p><p>// 查询MySQL版本:CMD 命令,输入mysql,回车进入命令行,根据系统提示,即可查看当前安装版本</p><p>// 数据连接工具:Navicat for MySQL</p><p>// F6命令打开两个console窗口,模拟两个不同的connection</p><p>----------</p><pre class="brush:sql;toolbar:false"><br/></pre><pre class="brush:sql;toolbar:false">mysql>COMMIT;
QueryOK,0rowsaffected
//T4时间console2
mysql>SELECT*FROMT_ORDERWHEREID=3;
//在console1提交事务后查询结果依旧没有改变
+----+-------+--------------+--------+
|id|name|order_no|status|
+----+-------+--------------+--------+
|3|订单3|DD_000000003|3|
+----+-------+--------------+--------+
1rowinset
//T5时间console2
//查询到最新数据的方式
//1.执行commit;当前事务结束;否则再次查询仍然与上次的查询在一个事务中,查询是上次查询结果的快照;
//2.SETautocommit=1;每次操作都是一个独立的原子性的操作,自动提交,每次都是一个独立的事务</pre><p>结论:</p><p>使用时应注意,在需要关闭自动提交的操作前将 autocommit = 0 操作完毕后,再将其改为 autocommit = 1 ;</p><p>在关闭AutoCommit的条件下,console 1 在T1和T2两个时间点执行的SQL语句其实在一个事务里,因此每次读到的其实只是一个快照,即一致性非阻塞读:InnoDB通过MVCC机制表示数据库某一时刻的查询快照,查询可以看该时刻之前提交的事务所做的改变,但是不能看到该时刻之后或者未提交事务所做的改变。但是,查询可以看到同一事务中之前语句所做的改变</p><p>未起作用</p><p>连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误</p><p>显示开启事务</p><p>注意:</p><p>1、不能将"关闭autocommit"作为缺省设置,否则在 innodb 表上执行的查询操作也将因为没有执行 commit 或者 rollback 而一直锁表!因此只能在需要时局部关闭 autocommit,并在操作完成后开启 autocommit</p><p>2、连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误</p><p>If a user has SUPER privilege, init_connect will not execute,(otherwise if init_connect will a wrong query no one can connect to server).</p><p>Note, if init_connect is a wrong query, the connection is closing without any errors and next command will clause 'lost connection' error.</p>