并发事务可能呈现问题
数据筹备
create table city( `id` int unsigned not null auto_increment primary key, `name` varchar(30) not null default '', `score` int not null default 0 )engine=innodb charset=utf8mb4;
脏读
一个事务读到了另一个未提交事务批改过的数据
session A | session B | 阐明 |
---|---|---|
set session transaction isolation level read uncommitted; | 将session A设置为读未提交 | |
begin; | begin; | |
insert into city(name) values('青岛'); | ||
select * from city; | 查出了青岛这条记录,脏读 |
不可反复读
一个事务读到了另一个已提交事务批改过的数据
session A | session B | 阐明 |
---|---|---|
set session transaction isolation level read committed; | 将session A设置为读已提交 | |
begin; | begin; | |
insert into city(name) values('大连'); | ||
select * from city; | 没有大连这条记录,脏读解决 | |
commit; | ||
select * from city; | 查出大连这条记录,不可反复读 |
幻读
幻读偏重的方面是某一次的 select 操作失去的后果所表征的数据状态无奈撑持后续的业务操作.
session A | session B | 阐明 |
---|---|---|
set session transaction isolation level repeatable read; | 将session A设置为可反复读 | |
begin; | begin; | |
insert into city(name) values('厦门'); | 自增id为3 | |
select * from city; | 没有厦门这条记录,脏读解决 | |
commit; | ||
select * from city; | 没有厦门这条记录,不可反复读解决 | |
insert into city(id,name) values(3,'厦门'); | Duplicate entry '3' for key 'PRIMARY'没有id为3的记录却报主键反复,幻读 | |
update city set score=1; | ||
select * from city | 呈现厦门这条记录,幻读 |
打消幻读
session A | session B | 阐明 |
---|---|---|
set session transaction isolation level serializable; | 将session A设置为串行化 | |
begin; | begin; | |
select * from city where id=1; | ||
update city set score=0 where id=1; | 该命令会始终期待A提交能力执行,成果相似for update |
隔离级别总结
脏读 | 不可反复读 | 幻读 | |
---|---|---|---|
读未提交 | 可能 | 可能 | 可能 |
读已提交 | 不能 | 可能 | 可能 |
可反复读 | 不能 | 不能 | 可能 |
串行化 | 不能 | 不能 | 不能 |
设置隔离级别
set [session|global] transaction isolation level 设置事务隔离级别;
设置事务隔离级别有四个值
read uncommittedread committedrepeatable readserializable
global
只对执行完该语句之后产生的会话起作用,对以后曾经存在的会话有效session
对以后会话的所有后续的事务无效,该语句能够在曾经开启的事务两头执行,但不会影响以后正在执行的事务,如果在事务之间执行,则对后续的事务无效.