锁:
mysql的锁分为全局锁、表锁、行锁、间隙锁
全局锁:Flush tables with read lock 可以全局设计库为只读
表锁:一种是表锁,一种是元数据锁(meta data lock,MDL)
lock tables t1 read,t2 wirte; 进行表锁
修改元数据时,进行MDL
读锁之间不互斥,因此可以有多个线程同时对一张表增删改查
读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行
行锁 是Innodb引擎才有的,MyISAM没有
间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。
间隙锁和行锁合称next-key lock,每个next-key lock是前开后闭区间
原则1:加锁的基本单位是next-key lock,next-key lock是前开后闭区间
原则2:查找过程中访问到的对象才会加锁
优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁
优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁
一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止
在进行select… for update/inser/ update语句的时候都会加上排他锁的next-key lock
在进行select… lock in share时 加共享锁。
参考: https://blog.csdn.net/qq_40378034/article/details/90904573
事物:
MVCC(Multi-Version Concurrent Control,基于多版本的并发控制)
MyISAM就不支持事务,而InnoDB是支持事务的。
脏读:即读取到别的事务未提交的数据
不可重复读:即某个事务前后多次读取,数据内容不一致。
幻读:即某个事务前后多次读取,读到的数据总量不一致。
事物隔离级别:
读未提交(Read Uncommitted): 支持脏读,每次读取最新数据。
读已提交(Read Committed): 支持不可重复读,不支持脏读。读取当前最新的已经提交的事物数据,每次事物创建的时候,都更新ReadView
可重复读(Repeatable Read): 不支持脏读和不可重复读。读取当前最新的已经提交的事物数据,第一次事物创建的时候,更新ReadView
串行化(Serializable): 全都不支持
Undo log:ysql在执行sql语句时,会将一条逻辑相反的日志保存到undo log中。undo log中记录的也是逻辑日志。主要用于事务回滚时恢复原来的数据。
在数据库中的每一行上,除了存放真实的数据以外,还存在着3个隐藏列——row_id、trx_id与roll_pointer。
其中roll_pointer会记录上一个版本Undo log 的地址,形成版本链
ReadView:一致性快照,在创建事物的时候会创建。
快照读:简单的select查询,即不包括 select … lock in share mode, select … for update,可能会读到数据的历史版本。
当前读:以下语句都是当前读,总是读取最新版本,会对读取的最新版本加锁
m_ids :在创建ReadView的那一刻,mysql中所有未提交的事务id集合。
min_trx_id
max_trx_id
creator_trx_id:即创建此ReadView的事务id
当undo log中的trx_id存在于ReadView中的时候,说明事物没有提交。
在Read Committed(RC)级别下,当前事务总是希望读取到别的事务已经提交的数据,因此当前事务事务会在执行每一次快照读的情况下都会去生成ReadView,实时更新m_ids,及时发现那些已经提交的事务。
在Repeatable Read(RR)级别下,当前事务当然也能够读取到别的事务已经提交的数据,但为了避免不可重复读,因此只会在执行第一次快照读的情况下去生成ReadView,之后的快照读会一直沿用该ReadView。
参考:https://blog.csdn.net/qq_33591903/article/details/120927753