# 查询数据库当前事务隔离级别 mysql> select @@global.transaction_isolation,@@transaction_isolation; +--------------------------------+-------------------------+ | @@global.transaction_isolation | @@transaction_isolation | +--------------------------------+-------------------------+ | REPEATABLE-READ | REPEATABLE-READ | +--------------------------------+-------------------------+ 1 row in set (0.00 sec) # 设置数据库事务隔离级别为 读未提交 set global transaction isolation level READ UNCOMMITTED; # 这一句话只针对当前客户端生效,因此两个客户端都需要 set session transaction isolation level READ UNCOMMITTED; # 关闭事务的自动提交 set autocommit = 0;1. 脏读
脏读概念:读取了其他事务未提交的数据,可能会造成严重的数据错误(理论上来说如果两个事务都正常提交就没问题)
| 事务A | 事务B |
|---|---|
| 开启事务 | 开启事务 |
| 查询TOM用户的余额 = 100 | 查询JOHN余额 = 1100 |
| JOHN给TOM转500 | |
| 查询TOM用户的余额 = 600 | |
| TOM用户花300买了个耳机 | |
| JOHN使用的支付转账设备异常,对支付状态校验失败,于是事务回滚 |
结果:数据异常,余额只有100 的TOM买了个300的耳机。脏读其实在MYSQL中一般是不会出现的,即使我们手动将MYSQL的隔离级别调整至最低的读未提交,MyISAM的表不支持事务,InnoDB在事务对某行进行修改的时候会自动加上行锁,相当于TOM买耳机的这个操作会被阻塞等待,因此不用对脏读太过担心。 2. 不可重复读
概念:由于第一次读取和第二次读取同一行记录的时间段中有另一个事务 修改 了数据,导致前后两次读取的结果不一致
| 事务A | 事务B |
|---|---|
| 开启事务 | |
| 查询TOM的余额 = 300 | |
| TOM买了300的耳机 | |
| 开启事务 | |
| 领导给TOM发了500工资 | |
| 提交事务 | |
| 再次查询TOM的余额 = 500,欸我怎么原300买300还剩500 |
结果:在事务A看来,事务期间对于TOM这一行的数据重复读取的时候获得了不一样的结果,数据异常。不可重复读可以通过设置数据库的隔离级别来进行规避,当数据库的事务隔离级别为Repeatable Read 或 Serializable 的时候,不可重复读情况消失,具体情况如下图所示:
3. 幻读
概念:事务执行中,有其他事务增删了某些字段,导致本事务没有得到消息,就感觉像出现幻觉一样。
| 事务A | 事务B |
|---|---|
| 开启事务 | |
| 查询用户JACK的余额 = 500 | |
| 开启事务 | |
| 删除用户JACK | |
| 提交事务 | |
| 给JACK用户存200 | |
| 查询JACK用户余额,欸怎么查不到JACK用户了?? |
结果:在事务A进行的过程中,B事务对同一张表的其他数据进行了修改没通知A,导致A做了一些无用的幻觉操作。
MYSQL避免幻读的方式:(摘自【MYSQL如何解决幻读】)
(1) 隔离级别可重复读下,快照读 MVCC + 当前读 Next-Lock Key(只在可重复读隔离级别下生效)
(2)隔离级别:SERIALIZABLE,在这个隔离级别下,事务在读操作时,先加表级别的共享锁,直到事务结束才释放;事务在写操作时,先加表级别的排它锁,直到事务结束才释放。也就是说,串行化锁定了整张表,幻读不存在的



