时间:2021-07-01 10:21:17 帮助过:22人阅读
2、读已提交 READ-COMMITTED / RC
解决了脏读的问题,但存在不可重复读、幻读的问题。
3、可重复读 REPEATABLE-READ / RR(默认)
解决了脏读、不可重复读的问题,但存在幻读的问题。是默认隔离级别,使用 MMVC机制实现可重复读。
4、序列化 SERIALIZABLE
解决了脏读、不可重复读、幻读的问题,可保证数据一致性,但各个事务完全串行化执行,性能最低。
事务隔离级别 |
脏读 |
不可重复读 |
幻读 |
读未提交(RU) |
是 |
是 |
是 |
读已提交(RC) |
否 |
是 |
是 |
可重复读(RR) |
否 |
否 |
是 |
串行化(Serializable) |
否 |
否 |
否 |
1、查看隔离级别命令
mysql> show global variables like ‘%isolation%‘;
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set
或者
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set
2、幻读问题
网上很多文章对幻读问题的解释是不对的。认为幻读问题是某个事务插入数据后导致前面的事务读取的数据记录集不一样。比如,事务A执行两次select操作得到不同的数据集,第一次select得到10条记录,第二次select得到11条记录。这并不是幻读问题,这是不可重复读问题,但在mysql 默认的RR隔离级别是不会出现的。
幻读,并不是说两次读取的结果不一样。幻读侧重的是某一次select 操作后得到的数据无法用于后面的业务操作。比如,select 某记录,发现不存在,准备insert 此记录时,发现此记录已存在,插入报错,此时就是因为发生了幻读。
解决办法,可以在select 时加上X锁,select ... for update 避免幻读问题。事务A在select时加入x锁后,其他事务插入操作需要等待,相当于间接地串行化执行事务。
3、测试验证
有一张user 表保存了用户记录,user表初始状态共3条记录,如下:
mysql> select * from user;
+----+-----------+-----+-----+---------+
| id | user_name | age | sex | address |
+----+-----------+-----+-----+---------+
| 1 | zhangsan | 20 | 0 | cd |
| 2 | lisi | 21 | 1 | bj |
| 3 | wangwu | 21 | 1 | sh |
+----+-----------+-----+-----+---------+
3 rows in set
事务A和事务B分别执行如下操作:
时间 |
事务A |
事务B |
T1 |
Begin; 事务A开始执行 |
|
T1 |
select * from user; 查询结果只有3条记录 |
|
T3 |
|
Begin; 事务B开始执行 |
T4 |
|
insert into user values(4, ‘test‘, 24, 0, ‘tj‘); 事务B插入1条id=4记录 |
T5 |
|
Commit; 事务B提交 |
T6 |
select * from user; 事务A再次查询,结果和上次查询一致,是看不到事务B已经插入的id=4的记录 |
|
T7 |
insert into user values(4, ‘test‘, 24, 0, ‘tj‘); 事务A再次插入id=4的记录报错,由于幻读导致事务A以为不存在id=4的记录,插入后报错 |
MySQL事务隔离级别总结
标签:插入数据 cal 没有 res 查看 概念 comm 结果 sel