并发事务可能呈现问题
数据筹备
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 uncommitted
read committed
repeatable read
serializable
global
只对执行完该语句之后产生的会话起作用, 对以后曾经存在的会话有效 session
对以后会话的所有后续的事务无效, 该语句能够在曾经开启的事务两头执行, 但不会影响以后正在执行的事务, 如果在事务之间执行, 则对后续的事务无效.