1、事务的隔离级别

MySQL的事务隔离级别有4种,由低到高分别是读未提交、不可重复读、可重复读和串行化。大多数数据库默认的事务隔离级别是不可重复读,而MySQL默认的事务隔离级别是可重复读。
image.png

2、不同隔离级别可能产生的问题

image.png

说明:
在可重复读的隔离级别下,Innodb使用MVCC和next-key locks解决幻读,MVCC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读。

3、普通读(快照读)

读取历史数据的方式,我们叫它快照读 (snapshot read)

4、当前读

读取数据库最新版本数据的方式,叫当前读 (current read)。

5、如何设置事务隔离级别

从MySQL 5.7.20开始,就增加了变量 transaction_isolation 作为 tx_isolation 的别名。从MySQL 8.0开始,变量 tx_isolation 被弃用并删除,使用 transaction_isolation 表示事务的隔离级别。

https://blog.csdn.net/max1231ff/article/details/103843560

  1. #查询当前正在执行中的事务
  2. select * from information_schema.INNODB_TRX

6、MySQL 8.0

#查看事务隔离级别
select @@transaction_isolation;

#或者
show variables like 'transaction_isolation';

#设置事务隔离级别
set transaction_isolation ='read-uncommitted';

7、MySQL 5.x

#查看事务隔离级别
select @@tx_isolation;

#设置事务隔离级别
set tx_isolation ='read-uncommitted';

8、测试数据

create table bank_innodb(
    id int not null auto_increment primary key,
    name varchar(30) comment '姓名',
    age int comment '年龄',
    balance decimal(18, 2) comment '余额'
)engine=InnoDB default charset=utf8;

insert into bank_innodb(name, age, balance) values('zhangsan', 22, 1000);
insert into bank_innodb(name, age, balance) values('lisi', 18, 2000);
insert into bank_innodb(name, age, balance) values('wangwu', 20, 3000);
insert into bank_innodb(name, age, balance) values('zhaoliu', 21, 4000);
insert into bank_innodb(name, age, balance) values('tom', 19, 5000);
insert into bank_innodb(name, age, balance) values('jack', 24, 6000);
insert into bank_innodb(name, age, balance) values('lilei', 22, 7000);
insert into bank_innodb(name, age, balance) values('lily', 18, 8000);

9、测试

① 脏读

#查看事务隔离级别
select @@transaction_isolation;

#设置事务隔离级别
set transaction_isolation ='read-uncommitted';

事务A

# 事务A

select @@transaction_isolation;

set transaction_isolation ='read-uncommitted';

# [脏读]
begin; -- 1

select * from bank_innodb; -- 2

select * from bank_innodb; -- 5 --7

commit; -- 8

事务B

# 事务B

select @@transaction_isolation;

set transaction_isolation ='read-uncommitted';

# [脏读]
begin; -- 3 

update bank_innodb set balance = balance + 100 where id = 1;  -- 4

rollback; -- 6

commit; -- 9

image.png

image.png

image.png

② 不可重复读

# 事务A

select @@transaction_isolation;

set transaction_isolation ='read-committed';

# [不可重复读]
begin; -- 1

select * from bank_innodb; -- 2

select * from bank_innodb; -- 5 --7

commit; -- 8
# 事务B

select @@transaction_isolation;

set transaction_isolation ='read-committed';

# [不可重复读]
begin; -- 1

select * from bank_innodb; -- 2

select * from bank_innodb; -- 5 --7

commit; -- 8

image.png

image.png

image.png

③ 幻读

# 事务A

select @@transaction_isolation;

set transaction_isolation ='repeatable-read';

# [幻读]
begin;

select * from bank_innodb ;

select * from bank_innodb ;

insert into bank_innodb(id,name,age,balance) values(9,'john',22,9000)

commit;
# 事务B

select @@transaction_isolation;

set transaction_isolation ='repeatable-read';

# [幻读]
begin;

select * from bank_innodb ;

insert into bank_innodb(id,name,age,balance) values(9,'lucy',22,9000)

commit;