MySQL锁机制

本文围绕MySQL的锁展开。介绍了锁在多线程环境下解决线程安全问题的作用,阐述了表级锁(元数据锁、数据表锁)和行级锁(排他锁、共享锁等)的分类及特点,还说明了行级锁的加锁过程。最后分析了使用行锁时可能出现的死锁情况及案例。

一、锁的作用

在多线程环境下执行i++,如果不加锁,大概率是得不到期望的结果。多线程并行对共享数据进行操作,会有线程安全的问题。对于数据库而言,多个客户端通过多个连接对数据进行操作,同样存在这个问题。分布式缓存Redis是单线程接受客户端请求,对于单个请求而言没有线程安全的问题。MySQL是支持多连接并行处理请求的,那么就面临线程安全的问题。多线程环境下,解决线程安全的问题,通常是用锁,悲观锁或者乐观锁,对于MySQL而言,使用乐观锁在应用层实现,通过版本号控制;悲观锁由数据库本身实现,下文介绍的是数据库本身设计的悲观锁。

二、锁分类

1.表级锁

元数据锁

分为读写锁,读锁与读锁不互斥,其他组合均互斥。对表执行DML的时候需要获取元数据读锁,对表执行DDL的时候需要获取写锁,在修改表结构的时候,是独占这张表的,不允许其他的DDL执行,也不允许DML执行,以保证数据的完整性。所以在执行DDL的时候要谨慎,选择业务低峰期,以避免执行DDL导致大量线上事务阻塞。

数据表锁

使用表锁的情况大致有两种:第一,在不支持行级锁的引擎中,比如MyISAM,只能用表锁。第二,在InnoDB中,能够利用索引的情况下会使用行锁,但如果使用表锁能带来更高的收益,那么就会选择表锁。比如,没有索引或者索引的区分度太低;全表更新;复杂事务,涉及多表级联,这些都有可能放弃行锁而选择表锁。表锁同样分为读锁和写锁,读锁与读锁之间不互斥,其余与写锁的组合都互斥。

2.行级锁

行级锁是InnoDB引擎支持的,通过对索引加锁,实现细粒度的控制,提高事务的并行度。不同的事务操作不同的行,对不同的行加锁,事务之间可以并行。

加锁过程

行级锁是加在索引上的,如果是主键索引,则直接锁定匹配的记录行。如果是二级索引,则先锁定匹配的二级索引记录,再根据id锁定对应的主键索引。具体的加锁规则根据隔离级别和索引类型而不同。
主键索引在RC级别和RR级别下,锁定对应的主键索引记录。
唯一索引在RC级别和RR级别下,锁定对应的唯一索引记录和对应的主键索引记录。
非唯一索引在RC级别下,锁定对应的二级索引记录和对应的主键索引记录。
非唯一索引在RR级别下,锁定对应的二级索引和对应的主键索引,并且会锁定二级索引记录之间的间隙,防止数据插入。
无索引在RC级别下,锁所有记录。
无索引在RR级别下,锁所有记录,并且加上记录间的间隙锁。

排他锁

排他锁是写锁,独占。

共享锁

共享锁是读锁,共享锁之间能并存,与排他锁互斥。

意向排他锁

意向锁之间是不互斥的。意向锁的存在是为了使得行锁与表锁能够高效的协调并存。假设有一个事务锁定了一行记录,另一个事务由于需要更新大量的记录,mysql判定需要全表扫描,于是去拿表级写锁,如果这个表有记录被行锁锁定,那么它不应该被表级写锁锁定。这就需要扫描,确认所有的行锁未被锁定,这样做显然太低效,于是有了意向锁。在获取排他锁之前先获取意向排他锁,在获取表锁之前只需要检查意向排他锁是否被锁定。如果被锁定,说明有行锁被锁定,这样就不需要对所有的行锁进行检查。

意向共享锁

意向共享锁的作用类似意向排他锁,在获取共享锁前需要先获取意向共享锁。

间隙锁

间隙锁主要是为了解决RR级别下的幻读问题。假设事务一更新数据,通过二级索引name=“张三”,定位到两条记录,那么锁定对应的二级索引和主键索引。另一个事务插入一条name="张三"的数据,提交事务二。事务一根据name="张三"去查询时,发现一条未被更新的数据,出现了幻读。解决这个问题的方案是在二级索引上锁定匹配到的记录的同时,锁定记录的区间,使得新的数据不能被插入。

三、死锁分析

在使用行锁过程中可能发生死锁。事务一持有行锁A,等待行锁B,事务二持有行锁B,等待行锁A,这就引发了死锁。如果不同的事务走了两个不同的二级索引,并且涉及相同的一批数据,拿锁的顺序又不相同,则有可能引发死锁。曾经就遇到过一个案例,定时任务多线程更新数据时出现了主键id冲突,原因就是多加了一个索引,两个更新请求又走了不同的索引。一般而言,最好是通过唯一标识单个的去更新数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值