四个事物等级
-
read uncommitted :有可能脏读
一个事务过程中读取到了,另一个事务的中途数据
-
read committed :有可能不可重复读
即在一次事务之间,进行了两次读取,但是结果不一样,可能第一次id为1的人叫“李三”,第二次读id为1的人就叫了“李四”。因为读取操作不会阻止其他事务
-
repetable read :有可能幻读
幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读
-
serializable :效率最低
可避免幻读。读加共享锁,写加排他锁。这样读取事务可以并发,但是读写,写写事务之间都是互斥的,基本上就是一个个执行事务,所以叫序列化
查看当前事务等级
SELECT @@global.tx_isolation, @@tx_isolation;
触发幻读
- 事前准备
create table t1 (
id int(10),
age int(3),
primary key(id)
)
- 触发过程
事务1 | 事务2 | 步骤 |
---|---|---|
begin | 1 | |
select * from t1 where id =1 | 2 | |
insert into t1 values (1,12) | 3 | |
insert into t1 values(1,12) | 4 |
在事务1中,先查询有没有id = 1的记录,如果没有就插入,但是在查询后,事务2先插入了,那么事务1就出现错误
解决幻读
事务1 | 事务2 | 步骤 |
---|---|---|
begin | 1 | |
select * from t1 where id =1 for update | 2 | |
insert into t1 values (1,12) | 3 | |
insert into t1 values(1,12) | 4 | |
commit | 5 |
在Step2执行后,数据库会加一个X锁(排它锁)。这时Step3执行后,会一直等待事务1执行完毕,当事务1 commit后,事务2就报错了