事物
mysql日志系统
binlog 数据同步与恢复时用的,
redolog 因为修改数据每次需要去磁盘找数据,再去修改,磁盘如果数据量多,速度就太慢了,所以数据先记录在redolog中,等高峰期过去,在同步到磁盘中,这样记录的时候只需要在redolog中顺序记录下去,而不需要直接去磁盘一个个去搜索要修改的数据再去修改了,这也就是随机io和顺序io,假设宕机了,可以从redolog中恢复数据,
二阶段提交
binlog 和 redolog 都会记录数据 ,无论记录哪一个,宕机后 另一个没记录,都会导致主从服务器数据不同步,所以产生了二阶段提交,简而言之,先提交一个,然后修改状态为prepare,然后提交另一个,事物提交后,状态修改为commit,这样数据恢复的时候,就会判断状态是否是commit了 ,如果不是 则称为无效数据
MVCC 多版本并发控制
并发情况
- 读读 不存在任何问题,也不需要并发控制
- 读写 有数据安全问题,脏读,幻读,不可重复读
- 写写 有数据安全问题,可能存在更新丢失
当前读 数据读取的时候读的都是最新的版本数据
触发情况:
select lock inshare mode 读锁
select for update 写锁
update,delete,insert
快照读 读取的可能是历史版本的数据
触发情况
select
隐藏列
DB_ROW_ID 隐藏主键,如果没有显式主键的话就会多一个隐藏主键
DB_TRX_ID. 创建或修改这条记录的最后一条事物id
DB_ROW_PTR 回滚指针,指向上一个版本的数据(以链式的结构存储在undolog回滚日志,链首是最新的,链尾是旧的记录,每一条数据的DB_ROW_PTR指向上个版本的数据,删除用purge …自己百度,我也不知道)
readview 事物进行快照操作的时候产生的读视图,就只有一个 select
readview下面有三个对应的字段
- trx_list readview 生成的那一刻,当前活跃的事务id列表
- up_limit_id 活跃列表中最小的事务id,就是trx_list中最小的id
- low_limit_id 系统尚未分配的下一个事物id
注:生成的readview 会根据可见性算法 来判断是否可以读取对应的数据(懒得看。。。搞脑子=<=)
可见性算法
1,如果DB_TRX_ID小于readview中的up_limit_id,则该行数据对当前事务可见。(解说:新增或修改 在开启readview之前,也就是select之前)
2,如果DB_TRX_ID>=readview中low_limit_id,则跳转步骤5执行。(解说:新增或修改在当前的select时刻还未操作,就要去步骤5 获取到 之前的记录返回)
3,trx_list为空,则该行数据可见。4,如果DB_TRX_ID>=readview中的up_limit_id,并且 DB_TRX_ID<readview中low_limit_id
判断若存在于活跃事务id列表,则不可见。 判断若不存在于活跃事务id列表,则可见。
5,根据回滚指针在undo log中取出一条记录,从1步骤重复判断,直到找到满足条件的记录,否则返回空。
在READ COMMITTED(读已提交) 中,每次select进行快照读时,readview都会重新生成,所以每次可以看到最新的结果,出现了 不可重复读这个问题,只能依靠锁来解决
在REPEATABLE READ(可重复读) 中,只有第一次次select进行快照读时,readview才会生成,之后每次都是延用第一次生成的readview,所以 在RR隔离级别中,事物里面每次查询的数据都是一样的,要么都是最新的数据,要么都是上个版本的历史数据,取决于第一次select是否在修改前还是修改后,成功解决里 不可重复读这个问题
注:即使如此,MVCC只能解决不可重复读,还是解决不了幻读这个问题,幻读需要靠锁来解决
- 幻读的解决,待补充。。。
注:图是网上的,如有侵权,请联系作者删除