隔离级别案例演示
1 read uncommitted
同时开启两个命令窗口
窗口1
mysql -uroot -p123456
use jinan2023
# 设置隔离级别
set session transaction isolation level read uncommitted;
select * from acocunt;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 2000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
# 开启一个事务
start transaction;
窗口2
mysql -uroot -p123456
use jinan2023
# 开启一个事务
start transaction;
# 执行修改
update account set money = money - 1000 where name = '张三';
此时并未提交事务
重回窗口1
select * from acocunt;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
此时能够发现,窗口1查询到了窗口2中未提交的数据。而此时数据库中的数据并未发生变化。
此时2提交数据(commit),数据库中的数据才真正完成变化。
read uncommitted 会出现脏数据
2 read committed
脏读问题
窗口1
# 设置隔离级别
set session transaction isolation level read committed;
select * from acocunt;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
窗口2
start transaction;
update account set money = money - 1000 where name = '张三';
依然不提交事务,此时数据库中的数据未发生变化
回到窗口1
select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
此时不会出现脏数据
不可重复读问题
两个窗口分别开启一个事务
start transaction;
窗口1
select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 0 |
| 2 | 李四 | 2000 |
+----+--------+-------+
窗口2
update account set money = money + 1000 where name = '张三';
窗口1的同一条sql语句,在窗口2 事务 未提交 、提交 ,查询到的数据是不同的,此时称之为不可重复读。
3 repeatable read
可重复读
窗口1
# 设置隔离级别
set session transaction isolation level repeatable read;
两个窗口同时开启事务
start transaction;
窗口1
select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 0 |
| 2 | 李四 | 2000 |
+----+--------+-------+
窗口2
update account set money = money + 1000 where name = '张三';
commit # 直接提交事务
窗口1再次查询
select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 0 |
| 2 | 李四 | 2000 |
+----+--------+-------+
此时窗口1也提交事务,才能看到最新的数据
commit
select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
此时已经解决了不可重复读的问题,但是很明显,数据出现了幻读
再比如:
两个窗口同时开启事务
1中查询id为3的用户,此时无数据。
2中新增一个用户,id为3,并且提交事务,新增成功
1中再次新增id为3的用户,新增失败。1中没有查询到id=3,但无法新增,再次查询依然没有id为3的数据,出现幻读。
4 serializable
在执行并发事务操作的时候,多个事务串联运行,只有当一个事务运行结束后,另一个事务才能运行。
serializable可以规避所有的并发事务,但运行效率也是最低的。