2023-09-27 09:27:52
浏览数 (1)
前言 MySQL默认的隔离级别是REPEATABLE-READ(可重复读)。虽然它可以提供一定程度上的数据一致性和隔离性,但并不能完全解决幻读问题。
幻读是指在一个事务内,由于其他事务的插入操作,导致当前事务中的查询结果发生了变化。在REPEATABLE-READ隔离级别下,只能保证在同一事务中相同的查询语句返回相同的结果,但无法防止其他事务插入新的数据,从而导致当前事务的查询结果发生变化。
为了解决幻读问题,可以将隔离级别设置为SERIALIZABLE(串行化)级别。在该级别下,MySQL会确保每个事务执行的时间顺序与提交的顺序一致,从而避免了幻读的问题。但是,这也会增加并发性能开销,因为它要求事务之间必须按顺序依次执行。
除了调整隔离级别,还可以使用锁机制来解决幻读问题。例如,通过使用行级锁或表级锁,可以在操作期间对数据进行锁定,从而避免其他事务对数据的修改。不过,需要注意在使用锁机制时要小心处理死锁等并发问题。
幻读演示 MySQL默认隔离级别REPEATABLE-READ(可重复读) 会话一
会话二
MySQL [test]> select * from t1;
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
4 rows in set (0.000 sec)
MySQL [test]> select * from t1;
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
4 rows in set (0.000 sec)
MySQL [test]> begin;
Query OK, 0 rows affected (0.000 sec)
注:开启事务一
MySQL [test]> begin;
Query OK, 0 rows affected (0.000 sec)
注:开启事务二
MySQL [test]> insert into t1 values(5);
Query OK, 1 row affected (0.000 sec)
MySQL [test]> select * from t1;
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
------
5 rows in set (0.000 sec)
注:插入一条数据5
MySQL [test]> select * from t1;
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
4 rows in set (0.000 sec)
注:因会话一未提交,所以在会话二事务里
是看不见更改后的结果的
MySQL [test]> commit;
Query OK, 0 rows affected (0.002 sec)
注:会话一执行事务提交
MySQL [test]> select * from t1;
------
| id |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
4 rows in set (0.000 sec)
MySQL [test]> update t1 set id = id 10;
Query OK, 5 rows affected (0.001 sec)
Rows matched: 5 Changed: 5
Warnings: 0
注:执行全表更新,id 10
MySQL [test]> select * from t1;
------
| id |
------
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
------
5 rows in set (0.000 sec)
注:当再次查看时,此时发现有5条数据被更改,产生幻读
MySQL [test]> select version();
-----------
| version() |
-----------
| 8.0.21 |
-----------
1 row in set (0.000 sec)
总结 在REPEATABLE-READ隔离级别下,通过使用多版本并发控制(MVCC)机制来解决快照读的幻读问题。该机制会为每个事务创建一个一致性视图,确保在事务执行过程中,读取的数据都是一致的快照,并且不受其他事务的影响。
然而,当前读(例如使用SELECT ... FOR UPDATE语句进行的读取操作)在REPEATABLE-READ隔离级别下仍然可能遇到幻读。因为当前读会获取行级锁来保证数据的一致性,但如果其他事务在当前读操作之后(但在当前事务提交之前)插入了新的数据行,那么当前事务再次执行相同的查询时,就会发现新增了一些未被读取到的新数据行,就像出现了幻觉一样,就像刚才的操作,在会话二未提交的事务里,会莫名其妙地看到第5条数据,这就是幻读问题。