MySql事务
事务
mysql的事务隔离级别默认是:可重复读。
说起事务,必须需要知道事务的四大特性(ACID):
- 原子性(Atomicity)
- 一致性 (Consistency)
- 隔离性 (Isolation)
- 持久性 (Transaction)
原子性
原子性就是说明事务的所有操作,要么全部成功,要么全部失败,不可能停留在中间的某个环节。
一致性
一致性就是一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。主要是针对业务的一致性,例如转账的业务场景,a账户的余额-1000,就必须有另外的一个账户+1000,还有就是余额不可能出现负数。
隔离性
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
持久性
在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
事务的隔离级别
事务的隔离级别主要是针对事务并发中产生的问题提供的解决方案。在事务的并发过程中,容易产生的问题有(级别递增):
- 脏读
- 不可重复度
- 幻读
脏读
主要是一个事务T1读取另外一个事务T2未提交的数据。如果T2在T1读取完毕后,进行回滚,就会出现问题。
不可重复读
主要是事务T1连续两次读取一条数据不一致。T1首次读取数据1(值为a),T2更改数据1(值a改为值b)并且提交,T1再次读取数据1(值为b),数据1变为T2更改的数据(值为b)。在同一个数据中读取同一个数据,前后值不一致。
幻读
主要是事务T1连续两次读取一个范围中的数据不一致的问题。例如表中有20条数据,主键(1~20),T1首次读取数据(id>15),结果为(16 - 20),T2插入数据(21)并且提交,T1再次读取数据(id>15),结果变为(16-21)。
针对于以上的问题,事务产生的隔离级别有(级别递增):
- 未提交读(READ-UNCOMMITED) : 未解决任何事务并发问题
- 读已提交(READ-COMMITTED):解决脏读
- 可重复读(REPEATABLE-READ) : 解决不可重复读
- 串行化(Serializable): 解决所有事务并发问题
针对以上的事务并发问题和事务的隔离级别验证如下:
可重复读:
第一步
select @@transaction_isolation;
第二步
现在设置mysql的事务隔离级别为未提交读然后再次查询:
set session transaction_isolation='READ-UNCOMMITTED
select @@transaction_isolation
可以看出mysql的事务隔离级别已经变为未提交读。
表test中有如下数据:
现在开启一个事务1查询name=22的数据:
第三步
begin;
select * from test where name = '22'
第四步
在新建一个mysql连接,开启一个事务2,修改name等于33后,不提交事务,然后在第一个连接中再次查询name=22:
更新成功。
第五步
由上图可以看出name=22已经改为33。说明读取到了事务2未提交的数据。
现在在将事务2回滚后事务1再次查询
由上面的流程可以看出,事务1连续读取name = ‘22’的数据在事务2对该条数据进行操作的过程中,出现了严重不一致的问题。
读已提交:
第一步
set session transaction_isolation = 'READ-COMMITTED'
select @@transaction_isolation
第二步
重复 可重复读步骤,在第五步的时候再次查询的结果如下:
第三步
提交事务2,事务1再次读取
可重复读:
第一步
set session transaction_isolation = 'REPEATABLE-READ'
select @@transaction_isolation
第二步
在进行读未提交的过程的第四步,提交事务2。如下:
第三步
再次读取test
结果可以看出数据还是没进行更改。
第四步
提交事务1,在重新开启事务进行查询:
数据已经变为33。
结果得出:可重复读已经解决不可重复读的并发问题。但是幻读的问题并没有解决。