(八)MySql事务
事务的特性:
- A,也就是原子性(Atomicity)。数据操作是不可分割
- C,就是一致性(Consistency)。一致性指的就是数据库在进行事务操作后,数据库的完整性约束不能被破坏。
- I,就是隔离性(Isolation)。它指的是每个事务都是彼此独立的,不会受到其他事务的执行影响。
- D,指的是持久性(Durability)。事务提交之后对数据的修改是持久性的,即使在系统出故障的情况下,比如系统崩溃或者存储介质发生故障,数据的修改依然是有效的。
1. 事务控制
通过SHOW ENGINES
命令来查看当前MySQL支持的存储引擎
事务的常用控制语句:
- START TRANSACTION或者 BEGIN,作用是显式开启一个事务。
- COMMIT:提交事务。当提交事务后,对数据库的修改是永久性的。
- ROLLBACK或者ROLLBACK TO [SAVEPOINT],意为回滚事务。意思是撤销正在进行的所有没有提交的修改,或者将事务回滚到某个保存点。
- SAVEPOINT:在事务中创建保存点,方便后续针对保存点进行回滚。一个事务中可以存在多个保存点。
- RELEASE SAVEPOINT:删除某个保存点。
- SET TRANSACTION,设置事务的隔离级别。
MySQL默认自动提交,可以配置MySQL的参数:
mysql> set autocommit =0; //关闭自动提交, 每条SQL语句都都需要用COMMIT进行提交。
mysql> set autocommit =1; //开启自动提交, 每条SQL语句都会自动进行提交。
MySQL中completion_type参数的作用:
- completion=0,这是默认情况。在执行下一个事务时,还需要START TRANSACTION或者BEGIN来开启事务,执行COMMIT的时候会提交事务
- completion=1,这种情况下,当我们提交事务后,相当于执行了COMMIT AND CHAIN,即当我们提交事务之后会开启一个相同隔离级别的事务,不需要START TRANSACTION或者BEGIN来开启事务
- completion=2,这种情况下COMMIT=COMMIT AND RELEASE,也就是当我们提交后,会自动与服务器断开连接。
事务案例1:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
BEGIN;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
运行结果(1行数据):
分析:整个SQL一共执行了2个事务,第一个是插入“关羽”,提交后执行成功,第二个是插入两次“张飞”,两次插入“张飞”在一个事务里,我们将name设置为了主键,也就是说主键的值是唯一的,那么第二次插入“张飞”时就会产生错误,然后执行ROLLBACK相当于对事务进行了回滚,所以我们看到最终结果只有一行数据,也就是第一个事务执行之后的结果,即“关羽”。
事务案例2:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
运行结果(2行数据):
分析:对于MySQL来说,因为在autocommit=1的情况下,MySQL会进行隐式事务,也就是自动提交,两次插入“张飞”就是两个事务,因此在进行第一次插入“张飞”后,数据表里就存在了两行数据,而第二次插入“张飞”就会报错。
事务案例3:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
SET @@completion_type = 1;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
运行结果(1行数据):
2. 事务隔离级别
事务并发处理可能存在的异常?
- 脏读:读到了其他事务还没有提交的数据。
- 不可重复读:在一个事务中,对某数据进行读取,发现两次读取的结果不同。这是因为有其他事务对这个数据同时进行了修改或删除。(锁解决)
- 幻读:在一个事务中,事务A根据条件查询得到了N条数据,但此时事务B更改或者增加了M条符合事务A查询条件的数据,这样当事务A再次进行查询的时候发现会有N+M条数据,产生了幻读。(串行解决)
事务隔离级别