mysql事务隔离级别

并发事务可能出现问题

数据准备

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 对当前会话的所有后续的事务有效,该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务,如果在事务之间执行,则对后续的事务有效.

你可能感兴趣的:(mysql)