一,问题:
MySQL事物操作的过程中,并发的场景下,经常是遇到以下问题:
1,可以读取未提交的数据的情况下,产生脏读(dirty reads)
事物A在修改了数据,但是尚未提交;这时事物B去读取这些已经修改的数据;但事物A因为某种原因回滚即rollback了,那么事物B读到数据最终并没提交,根本不存在,所以导致了脏读;
2,只能读取已提交的数据的情况下,产生不可重复读(non-repeatable reads)
事物B在查询了一次数据,然后继续执行其他操作;这时事物A修改了这些数据,并且提交了;事物B后来第二次去读这些数据,发现跟之前第一次读到数据不一样;这时因为事物A修改并提交了这些数据。所以数据不可重复读了。
3,同一事物开始之后读取的数据都不变,产生幻读(phantom read)
事物A开始读取数据,发现用户ID=4不存在;这时事物B插入一条用户ID=4的记录,并且提交了;然后事物A执行同样的插入,结果提示用户ID=4已经存在,这时事物A再去读取数据时,发现用户ID=4依然不存在,因为同一事物开始之后读取的数据都不变。这就导致了数据幻读
二,隔离级别
MySQL的隔离级别,以及会产生的问题
隔离解别 | 脏读 | 不可重复读 | 幻读 |
Read Uncommitted/可读取未提交 | Y | Y | Y |
Read Committed/只读取已提交 | N | Y | Y |
Repeatable Read(default)/可重复读 | N | N | Y |
Serializable/串行化 | N | N | N |
1,查看MySQL全局隔离级别和当前会话隔离级别
mysql> select @@global.tx_isolation,@@tx_isolation; +-----------------------+-----------------+ | @@global.tx_isolation | @@tx_isolation | +-----------------------+-----------------+ | REPEATABLE-READ | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in set (0.00 sec)
2,修改MySQL隔离级别
mysql> set session tx_isolation='read-uncommitted'; Query OK, 0 rows affected (0.00 sec) mysql> set global tx_isolation='read-uncommitted'; Query OK, 0 rows affected (0.00 sec) mysql> select @@global.tx_isolation,@@tx_isolation; +-----------------------+------------------+ | @@global.tx_isolation | @@tx_isolation | +-----------------------+------------------+ | READ-UNCOMMITTED | READ-UNCOMMITTED | +-----------------------+------------------+ 1 row in set (0.00 sec) mysql>
Leave a Reply