脚本宝典收集整理的这篇文章主要介绍了《MySQL是怎么运行的:从根儿上理解MySQL》(25)学习总结,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
文章的图片来源《MySQL是怎么运行的:从根儿上理解MySQL》,本篇文章只是个人学习总结,欢迎大家买一本正版小册看看,对于mysql是由浅入深的讲解非常细致
当事务需要对记录做改动的时候,就需要一个所结果和它进行关联
下面的整个流程其实就是T1先看看记录是不是有锁结构和它关联,如果没有那么T1需要创建一个,这个时候is_waITing是false的意思就是事务1已经获取到了锁。但是对于T2,发现记录已经有锁结构关联,但是仍然需要创建一个T2的锁结构,而且is_waiting是true说明获取锁失败需要等待前一个事务释放锁。
当T1执行完释放锁,那么T2的is_waiting就改变成false也就是这个时候T2获取到了锁。
不需要在内存生成锁结构,可以直接执行
获取了锁结构而且is_waiting是false
生成锁结构但是is_waiting是true
怎么解决脏读、不可重复读、幻读这些问题?
对于读可提交级别的readview避免了脏读问题,因为这些未提交的事务是无法被当前事务看到的。对于可重复读来说因为每次readview都是在第一次读的时候固定下来所以并不会产生幻读和不可重复读问题,因为readview相当于就是一个数据快照。
银行存款的问题,每次修改都需要加上锁,因为这种数据是不能够直接读取之前的记录,防止计算错误。所以在读写的时候需要加上锁,其它事务直接排队等待。
对于脏读是事务读取了另一个未提交事务的修改数据,但是现在加上锁,那么当前事务是无法读取记录的,所以不会产生脏读。对于不可重复读,由于当前事务无法事先读取正在修改当前记录,因为记录被另一个事务加上了锁,所以读取只能够等待另一个事务结束,最后不会发生不可重复读。但是对于幻读可能会难一点,因为innodb是支持行锁的。
事务利用Mvcc的select读取就是一致性读,而且不会加锁
T1访问记录1获取s锁,T2接着访问
如果T1获取记录1的x锁
select … lock in share mode
select … for update
定位B+树记录的位置,获取记录的x锁,进行delete mark操作,定位b+树的记录过程就是一个获取x锁的锁定读
插入使用的是隐式锁
现在用的都是行锁,粒度比较细,可以给表加上对应的锁
其它事务获取表的s锁
但是不能获取x锁
对于当前的表什么锁都不能获取
但是有一个问题如果表需要上一个s锁的时候需要确定表里面的记录没有上x锁,而且如果表要上x锁的时候要保证记录没有上s锁或者是x锁,那么怎么确定记录是不是有上锁?
意向锁可以快速确定表是否还有其他锁,并且可以上表级锁。
下面这种就是直接给id自增赋值
CREATE TABLE t (
id INT NOT NULL AUTO_INCREMENT,
c VArchAR(100),
Primary KEY (id)
) Engine=InnoDB CHARSET=utf8;
赋值原理的原因
@H_760_360@锁上一条记录,这种锁叫LOCK_REC_NOT_GAP。这种锁也有s锁和x锁的区分。就是我们上面说的那种
解决幻读可以通过rePEatable read隔离级别。两种方式
但是问题有来了gap锁只能锁定的当前记录的主键和前一条记录的主键间隙不能插入记录,那么如果现在插入的位置不确定,这个时候又应该如何加入这个gap锁?对于number为20之后的又应该如何锁定?这个时候就需要数据页的两个伪记录
为了防止在(20,+无穷)上面插入幻影记录,可以给最大的记录加上一个gap锁。
正经锁+gap锁合体,锁定当前记录,而且还能锁定前面的间隙不允许插入任何记录。
如果要插入一条记录,刚好这个位置被加上了gap锁,这个时候需要生成一个插入意向锁结构。
假设现在要插入4、5的记录,那么由于gap锁会被阻塞。就需要锁结构来让这些事务进行排队等待。而且对于这些插入意向锁是可以被多个事务同时获取并且插入的。
通常insert并不会加锁,但是插入过程中,另一个事务
上面都可能会产生脏写问题。
事务id其实就是一个隐式锁,如果某个事务对插入的记录加上s锁或者是x锁都会检查记录的事务id,如果事务id不是自己,那么就需要给他创建一个锁结构,并且给自己也创建一个锁结构等待前一个事务结束。
在不同记录上面加锁的时候
那么这些记录的锁就可以放到一个锁结构上面。
锁所在事务信息:哪个事务生成这个锁,记录当前事务的信息(只是一些指针)
索引信息:加锁的记录属于哪个索引
表锁/行锁信息
type_mode:32位数分成lock_mode、lock_type和rec_lock_type
一堆bit
也就是上面的n_bits,每个页头都有一个heap_no,Infimum是0,Supremum是1。每次添加一条数据heap_no都会+1,每个bit位映射到一个页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s5xgWHAX-1636338643714)(…/…/…/…/…/AppData/Roaming/Typora/typora-user-images/image-20211107164322294.png)]
T1给number=15的记录加s锁,首先需要给表加上IS锁
加的是行锁
n_bits = (1 + ((n_recs + LOCK_PAGE_BITMAP_MargIN) / 8)) * 8
n_recs是当前有多少条记录,LOCK_PAGE_BITMAP_MARGIN默认64。
下面就是整个锁结构
[外链图片转存中…(img-7NmfIS6U-1636338643714)]
下面就是整个锁结构
[外链图片转存中…(img-9gjjWqys-1636338643715)]
[外链图片转存中…(img-tgcpa5xL-1636338643716)]
以上是脚本宝典为你收集整理的《MySQL是怎么运行的:从根儿上理解MySQL》(25)学习总结全部内容,希望文章能够帮你解决《MySQL是怎么运行的:从根儿上理解MySQL》(25)学习总结所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。