4.幻读如果一个事务A先根据没用搜索条件查询到一些记录,在该事务未提交前,另外一个事务写入(delete,update,insert)了符合搜索条件的记录 , 这时候事务A再次读取,发现数据条数和第一次读取的不同,如同出现了幻觉,称之为幻读

文章插图
事务A读到事务B提交后的数据似乎很合理,但是我们想象这样一种场景:你有一个需求将会公司的男性员工了女性员工查询进行展示,你先查询了总数为100人,然后查询男性的总数50人,后查询女性人数准备在页面展示共100人,其中男50人,女50人 , 结果这是管理信息的人发现有一位员工性别错误录入了,将其从男修改为女,这时候你读取事务就是女51人了,你在主页显示了共100人,其中男50人,女51人
三丶隔离级别1.Read UnCommitted 读未提交在此隔离级别下,会发生脏读,不可重复读,和幻读
2.Read Committed 读已提交在此隔离级别下,会发生不可重复读,和幻读
3.Repeatable Read 可重复读在此隔离级别下,可能发生幻读
4.Serializable 可串行化在此隔离级别下,不会发生脏读,不可重复读,和幻读
其中脏写是对一致性影响最严重的,无论是何种隔离级别,都不允许脏写发生,innodb使用锁保证不会出现脏写现象,第一个事务更新某条记录的时候 , 会给这条记录加锁,另外一个事务在此更新的时候,需要等待第一个事务提交释放锁后更新 。隔离级别越高,其并发能力越低 。
四丶Mysql设置隔离级别默认隔离级别可重复读
1.设置全局隔离级别SET GLOBAL TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE),此命令只对执行语句后新产生的会话有效,对当前已经存在的会话无效
2.设置会话隔离级别SET SESSION TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED , READ COMMITED,REPEATABLE READ,SERIALIZABLE),对当前会话后续事务有效,该语句可以在已开启的事务中执行,但是不会影响当前正在执行的事务,如果在事务之间执行 , 只会对后续的事务有效
3.设置下一个事务的隔离级别SET TRANSACTION ISOLATION LEVEL 期望的隔离级别(可选READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE) 只对当前会话的下一个即将开启的事务有效,下一个事务执行完后,后续事务将恢复到之前的隔离级别,该语句不能再已经开启的事务中执行,否则会报错 。
4.指定服务器的隔离级别在启动的时候使用--transaction-isolation=xxx即可执行默认隔离级别
五丶MVCC原理下面讨论记录对当前事务是否可见都是基于当前事务中执行的查询是快照读(普通查询),对于当前读(select xxx for update,select xxx lock in share mode)是不通用的1.版本链对于InnoDB存储引擎来说 , 其聚簇索引记录中包含两个隐藏列:
- trx_id:一个事务每次对聚簇索引记录做出改动的时候 , 都会把该事务的事务id复制给此列
- roll_point:每次对某条聚簇索引记录进行改动的时,都会把旧的版本写入到undo 日志中,此列相当于一个指针,指向修改前的信息

文章插图
每次修改都会形成Undo 日志,所有版本的数据会通过roll_point串联成一个链表,称之为版本链 , 头节点是当前记录的最新值 。利用版本链控制多个并发事务访问相同记录时的行为称为MVCC多版本并发控制 。
其实在undo日志中,只记录被更新列的信息,而不是记录全部的信息,对于没有记录的列,会通过版本链找少一个版本中的对应列的信息,直到找到聚簇索引叶子节点中的内容2.Read View对于使用Read Uncommitted隔离级别的事务,可以读取到没提交的数据,那么直接读取最新的版本即可 。对于Serializable隔离级别,innodb直接通过加锁来访问记录 。对于read committed 和 repeatable read隔离级别的事务,都必须保证督导的数据是已经提交事务修改过的记录 , 那么如何判断版本链中的哪个版本的数据是当前事务可见的昵?
innodb 使用的Read View
2.1 read view 的结构

文章插图