我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文讨论mysql的数据回滚操作rollback,人生路上有很多遗憾,多想再来重走一次。这个理念体现在mysql里面,就是rollback命令,给你一次数据重来的机会。但是,也不是想rollback就一定会rollback成功的,这也是有条件的。这些就是在本文里面,苏南大叔要阐述的主要内容。

苏南大叔:mysql事务,如何回滚数据?rollback操作是否一定会成功? - mysql-rollback
mysql事务,如何回滚数据?rollback操作是否一定会成功?(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验故事。本文描述mysql数据变更的后悔药rollback命令。测试环境:win10mysql@5.7.26mysql-front@5.3

rollback 与 transaction

开始语句是用于界定事务回滚的范围的,也就是说回滚到什么位置,所以不用小看这两条开始语句。事务开始transaction的标志性语句,包括:

  • start transaction;
  • begin;

回滚rollback是事务transaction中的一个操作,可以单独使用。如果没执行这两条语句的话,就是当前mysql线程开始的时候的表状态作为起始状态。这个事情就比较不可控了。本文的代码里面,begin;的位置很关键,如果没有begin;的合适调用,InnoDB最终也得不到任何数据。那是因为本文的实验表的初始状态就是个空表。

事务在commit命令之后,表示事务结束。后续的就是另外一个事务了。

rollback 与 InnoDB

只有mysqlInnoDB存储引擎才支持事务,所以任何类型不是InnoDB的数据表都不支持事务,也就不会支持rollback数据回滚。典型的类型就是MyISAM类型的数据表,并不支持事务,无法处理rollback命令。(但是并不会报错)

同一个数据库里面,可以有不同存储引擎的数据表。存储引擎是跟着“表”走的,并不是跟着“库”走。

参考文章:

InnoDB类型[有条件回滚]

回滚rollback只和数据表存储类型有关,只有innodb类型数据表支持事务,支持回滚rollback

定义一个InnoDB类型的表:

DROP TABLE IF EXISTS `innodb`;
CREATE TABLE `innodb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `innodb` VALUES (1,'苏南大叔'),(2,'sunan大叔');

两次rollback测试代码:

# 第一次
BEGIN;
delete from innodb;
rollback;
select * from innodb;

# 第二次执行的效果是有区别的
delete from innodb;
rollback;
select * from innodb;

开启autocommit,然后测试:

set autocommit = 1;

苏南大叔:mysql事务,如何回滚数据?rollback操作是否一定会成功? - autocommit开启则影响rollback效果
mysql事务,如何回滚数据?rollback操作是否一定会成功?(图5-2)

关闭autocommit,然后测试:

set autocommit = 0;

苏南大叔:mysql事务,如何回滚数据?rollback操作是否一定会成功? - autocommit关闭则不影响rollback效果
mysql事务,如何回滚数据?rollback操作是否一定会成功?(图5-3)

MyISAM类型[不支持回滚]

回滚rollback只和数据表存储类型有关。只有MyISAM类型数据表不支持事务,不支持回滚rollback

定义一个MyISAM类型的表:

DROP TABLE IF EXISTS `myisam`;
CREATE TABLE `myisam` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `MyISAM` VALUES (1,'苏南大叔'),(2,'sunan大叔');

开启autocommit,然后测试:

set autocommit = 1;
BEGIN;
delete from myisam;
rollback;
select * from myisam;

苏南大叔:mysql事务,如何回滚数据?rollback操作是否一定会成功? - myisam-rollback
mysql事务,如何回滚数据?rollback操作是否一定会成功?(图5-4)

关闭autocommit,然后测试:

set autocommit = 0;
BEGIN;
delete from myisam;
rollback;
select * from myisam;

苏南大叔:mysql事务,如何回滚数据?rollback操作是否一定会成功? - myisam-rollback2
mysql事务,如何回滚数据?rollback操作是否一定会成功?(图5-5)

rollback 与 autocommit

rollbackautocommit无关,只和inndbdb有关。

  • 表引擎是InnoDB的情况下,autocommit无论取值什么,rollback都能生效。
  • 表引擎是MyISAM的情况下,autocommit无论取值什么,rollback都不能生效,但是也不报错。

参考文章:

rollbackinnodb表中,在第一次执行之前,确实和autocommit无关。但是,如果是rollback正常回滚之后,却和autocommit有关了。因为当autocommit=1的情况下,rollback后,会有个自动隐藏的commit操作。后续的rollback就可能达不到预期了。

rollback 生效条件

存储引擎autocommitrollback第二次rollback
InnoDBOn恢复到begin最多恢复到上一次rollback
InnoDBOff恢复到begin恢复到begin
MyISAMOn不生效不生效
MyISAMOff不生效不生效

rollback只和transaction有关,同时,只有innodb支持transaction。结论是:只有在inndb类型的数据表里面,才可能被rollback

绝对不能rollback的情况

truncate以及alter这种改了表属性的语句,是不会被回滚的。无论如何都无法回滚。比如:

truncate table test;

或者:

alter table test add description varchar(50);
truncate会修改AUTO_INCREMENT属性。

结语

人生没有回头路,珍惜当下。更多苏南大叔的mysql经验文章,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   mysql