MySQL 事务
数据库事务
事务是一个抽象的概念,它对应着一个或多个数据库操作,这些操作要么全部成功,要么全部失败。事务有四大特性,即 ACID:
事务可以分成这么几个状态:
事务的这几个状态的流转路径如下:
从图中可以看出,当事务处于 committed 或者 aborted 状态时,这个事务的生命周期才算结束。对于 committed 的事务来说,该事务对数据库所做的修改将永久生效;对于 aborted 状态的事务,该事务对数据库所做的所有修改都会被回滚到没执行该事务之前的状态。
MySQL 事务语法
在常见的 MySQL 存储引擎中,InnoDB 支持事务,MyISAM 不支持事务。下面我们学习下 MySQL 事务的语法:
开启事务
MySQL 支持两种方式开启事务:
(1) BEGIN
BEGIN;
<要在事务中执行的 SQL 语句>
(2) START TRANSACTION
START TRANSACTION; -- 默认访问模式是 READ WRITE 读写模式
<要在事务中执行的 SQL 语句>
START TRANSACTION 后面还可以跟几个修饰符(READ ONLY、READ WRITE、WITH CONSISTENT SNAPSHOT):
-- 开启一个只读事务
START TRANSACTION READ ONLY;
-- 开启一个读写事务
START TRANSACTION READ WRITE;
-- 开启一个只读事务和一致性读
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT;
-- 开启一个读写事务和一致性读
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT;
提交事务
手动提交事务
使用 COMMIT 语句可以手动提交事务,如:
BEGIN;
<要在事务中执行的 SQL 语句>
COMMIT;
自动提交事务
MySQL 有一个 autocommit 系统变量控制是否自动提交事务:
mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
可以看到 autocommit 默认为 ON 开启自动提交,如果不显式使用 BEGIN 或 START TRANSACTION 开启事务,那么每一条语句都会开启一个独立的事务并自动提交。
隐式提交事务
有些特殊的语句会导致事务提交,这就是隐式提交。常见的会导致隐式提交的语句有:
DDL 语句(操作数据库、表、视图、存储过程等),如 CREATE TABLE、ALTER TABLE、CREATE PROCEDURE
隐式使用或修改 mysql 数据库中的表,如 ALTER USER、GRANT、SET PASSWORD
当前事务未提交或回滚时就又使用 START TRANSACTION 或 BEGIN 开启事务
锁定相关语句,如 LOCK TABLES、UNLOCK TABLES
加载数据的语句,如 LOAD DATA
关于 MySQL 复制的一些语句,如 START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO
一些其他语句,如 ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET
回滚事务
如果事务在执行过程中遇到了某些错误而无法继续执行的话,事务会自动回滚。同时,MySQL 也支持使用 ROLLBACK 语句手动回滚事务,如:
BEGIN;
<要在事务中执行的 SQL 语句>
ROLLBACK;
但是有时候我们不想回滚到事务开启时的最初状态,而是想回滚到中间的某个状态,为此 MySQL 引入了一个保存点(savepoint)的概念。有了保存点之后,使用 ROLLBACK 的时候可以指定回滚到哪个保存点,语法如下:
SAVEPOINT <保存点名称>; -- 创建保存点
ROLLBACK TO <保存点名称>; -- 回滚到某个保存点
如果想要删除保存点,可以执行这个语句:
RELEASE SAVEPOINT <保存点名称>;