MySQL InnoDB所提供的事务满足ACID的要求,事务是通过事务日志中的redo log和undo log来实现原子性(undo log)、一致性(undo log)、持久性(redo log),事务通过 锁机制实现隔离性。
1、事务隔离级别与实现
READ-UNCOMMITTED : "读未提交"。
READ-COMMITTED : "读已提交" 或者 "读提交"。
实现机制:修改时加排他锁,直到事务提交后才释放,读取时加共享锁,读取完释放。
REPEATABLE-READ : "可重复读" 或者 "可重读"。mysql默认使用级别。
实现机制:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁。采用"一致性非锁定读"的机制提高了数据库并发性(非锁定读),使用 MVCC (多版本并发控制)实现。
SERIALIZABLE : "串行化"。
实现机制:所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。采用的是RangeS_S模式,锁定检索范围为只读,这样就避免了幻影读问题,表级锁。
show processlist ;#查看连接线程
show variables like 'tx_isolation'; #查看隔离级别
mysql> set @@session.tx_isolation='READ-UNCOMMITTED'; #设置当前线程隔离级别,GLOBAL全局
Query OK, 0 rows affected, 1 warning (0.00 sec)
启动两个不同线程的客户端:
![3a4fee3ff79333ec1e49b8a774430b2f.png](https://i-blog.csdnimg.cn/blog_migrate/bc8da5b8a263e03f1eb82ad972c832b8.jpeg)
设置事务隔离级别并查看:
![d115501b8a66550850a45f9dde825506.png](https://i-blog.csdnimg.cn/blog_migrate/cb9a095bcbd72d1033775a74367e9d6b.jpeg)
读未提交:
![7311b3d203319a252f74344d32254182.png](https://i-blog.csdnimg.cn/blog_migrate/f9f52cdc3e83ac6a68abe876a52b747b.jpeg)
![0659d118d0bab7e3a7c5e5630e94bf67.png](https://i-blog.csdnimg.cn/blog_migrate/d1427c79949d82c870c58ff457f991f0.jpeg)
读已提交:
![bda0c690b2294c3f58c7d1880b3b446c.png](https://i-blog.csdnimg.cn/blog_migrate/405a22cc4d256e7bc3644811f87fcbec.jpeg)
![4d58dc56a4dc3750b80841819c118398.png](https://i-blog.csdnimg.cn/blog_migrate/636cf0cddf8aa411cc69134c2d02a9b5.jpeg)
可重复读:
![3006e238d3add85b211342790044994e.png](https://i-blog.csdnimg.cn/blog_migrate/7b5e6dcab595f19c0ac2524eda4cb9d4.jpeg)
![2f9d6c8bf241ab5b8e90988e20ba39fb.png](https://i-blog.csdnimg.cn/blog_migrate/c58dcd11cb8684690c4add555cef513a.jpeg)
注意:
※ 可重复读仅在事务开始时创建一次快照,而读提交每次执行语句都会重新创建一次快照。
可重复读-幻读:
![dc8c229c50ee6dc4eeb33cf0f6bef682.png](https://i-blog.csdnimg.cn/blog_migrate/30a3531eafd85b7dd0611725faeb5b9d.jpeg)
可重复读-并发写阻塞(索引列使用行锁):
![8dfaee38658fd0ac8d90b825024c7c84.png](https://i-blog.csdnimg.cn/blog_migrate/ecf71b8a1cf02ca7267cdbcc14dd27e5.jpeg)
可重复读-并发写阻塞(非索引列使用表锁):
![a50ac4e2b2d301bf421f4a48c849f6be.png](https://i-blog.csdnimg.cn/blog_migrate/227bdc6bd5e270cceba766e20eebac12.jpeg)
可重复读-间隙锁:
![adbfec24d41f85eda73287071777b2b9.png](https://i-blog.csdnimg.cn/blog_migrate/d51498402d2109d374b820a4a9cbd85b.jpeg)
![b4d6e6dc2a9a160696234df576998177.png](https://i-blog.csdnimg.cn/blog_migrate/20c73bfa13542c0493bf6fd5c0fd2f9d.jpeg)
Next-Key锁:
![913cbfe781b61bb8fe2e6f901af866d7.png](https://i-blog.csdnimg.cn/blog_migrate/dc64f82fd9f8b4bcb4de56f284711970.png)
注意:
※ age为索引,当操作age=28时,不仅针对该记录加行锁,且两侧加间隙锁,33<=age不受影响;
age不为索引时,对整表加间隙锁;
※ 并发写问题利用行锁解决,解决幻读用间隙锁,MySQL 把行锁和间隙锁合并「Next-Key锁」使用,解决并发写和幻读。
2、脏读、幻读、不可重复
脏读:当前事务可以查看到别的事务未提交的数据(侧重点在于别的事务未提交)。
幻读:幻读的侧重点在于新增和删除(数据量的变化)。表示在同一事务中,使用相同的查询语句,第二次查询时,莫名的多出了一些之前不存在数据,或者莫名的不见了一些数据(MySQL 的可重复读隔离级别通过间隙锁解决了幻读问题,但插入相同主键会冲突)。
不可重读:不可重读的侧重点在于更新修改数据(数据内容的更新)。同一事务中,查询相同的数据范围时,同一个数据资源莫名的改变了。
3、隔离界别区别
事务的隔离级别越高,隔离性越强,数据问题越少,并发能力越弱。
![d3617298863a55260508796e1650a534.png](https://i-blog.csdnimg.cn/blog_migrate/9392d6befa745d6b420b0015dee1189b.jpeg)