0
点赞
收藏
分享

微信扫一扫

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)


一、在循环中提交

  • 开发人员喜欢在循环中进行事务提交,这种方法有两个缺点:出现错误难处理以及效率低

演示案例

  • 创建一个表

create table t1( a int not null, b varchar(80) )engine=innodb;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_使用自动回滚

  • 下面一个存储过程

delimiter // create procedure load1(count int unsigned) begin declare s int unsigned default 1; declare c char(80) default repeat('a',80); while s<=count do insert into t1 select NULL,c; commit; set s=s+1; end while; end; // delimiter ;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_使用自动回滚_02

  • 默认情况下,SQL语句都是自动提交的,也就是说在存储过程中,insert语句之后都会有一个隐式的commit操作,因此上面的存储过程也等价于:

delimiter // create procedure load2(count int unsigned) begin declare s int unsigned default 1; declare c char(80) default repeat('a',80); while s<=count do insert into t1 select NULL,c; set s=s+1; end while; end; // delimiter ;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_不好的事务习惯_03

  • 这两个存储过程有两个问题:
  • ①如果循环执行时发生错误,数据库会停留在一个未知的位置,因此很难进行处理
  • ②性能问题:因为事务每提交一次就需要写一次重做日志,因此效率比较低
  • 现在我们运行上面的两个存储过程,观察它们的运行的时间,可以看到差不多都为两秒多:

call load1(10000); truncate table t1; call load2(10000);

二、使用自动提交

  • 自动提交不是一个好的习惯,因为这会是初级DBA容易犯错,另外还可能使一些开发人员产生错误的理解,如我们在上面介绍到的循环提交问题
  • MySQL数据库默认设置使用自动提交(autocommit),可以使用下面的语句来关闭自动提交功能

set autocommit=0;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_不好的事务习惯_08

  • 当然也可以使用start transaction或begin来显式开启一个事务。在显式开启事务之后,在默认设置下(即参数completion_type=0),MySQL会自动执行SET AUTOCOMMIT=0的命,在使用commit或rollback结束一个事务之后自动执行SET AUTOCOMMIT=1

不同编程语言API的自动提交

  • 对于不同语言的API,自动提交也是不同的
  • MySQL C API默认的提交方式是自动提交
  • MySQL Python API则会自动执行SET AUTOCOMMIT=0,禁用自动提交

三、使用自动回滚

  • InnoDB支持通过定义一个HANDLER来进行自动事务的回滚操作,如在一个存储过程中发生了错误会自动对其进行回滚操作

演示案例

  • 因此我发现很多开发人员喜欢在应用程序中使用自动回滚,例如:
  • 创建一个表

create table b( a int not null default 0, primary key(a) )engine=innodb default charset=latin1;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_在循环中提交_09

  • 存储过程定义了一个exit类型的HANDLER,当捕获到错误时进行回滚:

delimiter // create procedure sp_auto_rollback_demo() begin declare exit handler for sqlexception rollback; start transaction; insert into b select 1; insert into b select 2; insert into b select 1; insert into b select 3; commit; end; // delimiter ;

MySQL(InnoDB剖析):45---事务之(不好的事务习惯:在循环中提交、使用自动提交、使用自动回滚)_使用自动回滚_10

  • 因为表中a字段为主键,因此第三条insert语句会抛出错误,运行如下,表格没有插入任何数据:
举报

相关推荐

0 条评论