MySQL加锁详解
一、锁的内存结构
在MySQL中,锁本质上是内存中的数据结构,当对一条记录加锁时,实际上是在内存中生成一个与该记录相关联的锁结构,这个锁结构主要由以下6部分组成:
1、锁所在的事务信息:存储锁对应的事务信息,通过指针可以获取更多关于该事务的信息。
2、索引信息:对于行级锁,记录的是加锁记录所属的索引。
3、表锁或行锁信息:包括表锁和行锁的具体信息。
4、type_mode:由32个bit组成,分别表示lock_mode、lock_type、lock_wait和rec_lock_type。
5、其他信息:一些额外的数据。
6、与heap_no对应的比特位:用于指向具体的记录。
二、加锁流程
1、加锁的基本流程:
当一个事务T1想对某条记录进行改动时,会首先检查内存中是否有与该记录关联的锁结构,如果没有,则创建一个锁结构并关联到该记录上。
如果另一个事务T2也想访问这条记录,发现已有锁结构,则会生成自己的锁结构并将is_waiting属性设置为true,表示等待。
当事务T1提交后,释放其锁结构,并检查是否有其他事务在等待,如果有,则唤醒这些事务继续执行。
2、根据主键加锁:
基于主键(聚簇索引)进行等值查询时,如果对应的值存在,则添加标准记录锁Record Lock;如果不存在,则在查询id所在的索引间隙添加间隙锁Gap Lock。
基于主键进行范围查询时,采用Next Key Lock添加行锁。
3、根据二级索引加锁:
先在辅助索引上加锁,然后在聚簇索引上加锁。
聚簇索引上的加锁算法采用Record Lock,只锁记录不锁间隙。
4、根据非索引字段查询加锁:
不走索引时,会在聚簇索引上加锁,采用Next Key Lock算法,可能会锁定全表范围,但注意,这是通过Next Key Lock实现的,而不是直接的表级锁。
5、加锁规律:
InnoDB默认采用Next Key Lock加锁,前开后闭。
行锁都是加在索引上,如果通过聚集索引查询则在聚集索引上加锁,通过辅助索引查询则需要同时在辅助索引和聚集索引上加锁。
查找过程中访问到的索引才会加锁,基于主键和唯一索引进行等值查询时,Next Key Lock会退化为行锁Record Lock。
三、影响锁的因素
1、数据库的隔离等级:不同的隔离等级会影响加锁的行为和粒度。
2、SQL语句和当前数据库数据:共同决定执行时数据库生成的锁模式、类型和数量。
四、锁信息查看
1、查看锁的SQL语句:可以使用SHOW PROCESSLIST命令查看当前系统的线程情况,包括每个线程的进程ID、用户、主机、执行的命令、耗时、状态和信息等。
2、data_locks表字段说明:可以通过查询information_schema库下的data_locks表来查看更详细的锁信息。
3、lock_mode说明:锁的模式分为共享锁(S)、排他锁(X)等,不同的模式有不同的兼容性和阻塞行为。
五、FAQs
Q1: 什么时候使用表锁?什么时候使用行锁?
A1: 表锁适用于并发较低、以查询为主的应用,如中小型网站,而行锁适用于按索引条件高并发更新少量不同数据,同时有并发查询的应用,如OLTP系统,InnoDB存储引擎同时支持这两种锁,默认情况下采用行级锁。
Q2: 如何查看当前的锁信息?
A2: 可以通过SHOW PROCESSLIST命令查看当前系统的线程情况,包括每个线程的状态和是否被锁定等信息,也可以查询information_schema库下的data_locks表来获取更详细的锁信息。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1239431.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复