章
目
录
在数据库相关的面试中,表锁和行锁是经常被问到的知识点。哪怕日常开发里你只是进行常规的增删改查操作,实际上也在不经意间和它们打过交道。接下来,咱们就详细聊聊这两种锁,帮助大家深入理解,面试时能应对自如。
一、表锁和行锁的基本应用场景
(一)行锁的使用场景
当执行数据更新操作时,比如使用 update
语句,数据库会默认开启事务,并依据设定的条件加锁,通常默认加的是行锁。打个比方,假设有一个更新操作正在执行,此时其他针对同一条记录的更新请求就无法进行。这是因为行锁的主要作用就是防止在修改过程中,其他事务对同一条记录进行修改,进而产生脏数据。就好比你正在修改一份重要文件,得保证修改期间没人来捣乱,行锁就是这个“把门的”。
(二)表锁的使用场景
而在修改表结构的时候,比如更改表的名称或者字段类型,以MySQL数据库为例,它会把当前表锁住。在表被锁住期间,所有针对这个表的增删改查事务都得等待,只有当修改完成并释放表锁后,这些事务才能继续执行。这就像你要重新装修房子,在装修期间,其他人都不能随意进出一样。由于表锁的锁定范围比较广,所以在往生产环境同步表结构修改时,通常会选择在夜间进行,因为这时系统的用户较少,对业务的影响相对较小。
二、行锁的细分类型
行锁相对表锁来说要复杂一些,它主要分为记录锁、间隙锁和临键锁这三种类型。
(一)记录锁
还是以更新数据为例,如果 where
条件匹配的是索引,比如主键索引 id
,当条件为 id = 1
时,数据库就会给 id
等于 1
的这条记录加上一个锁,这就是记录锁。它只针对当前这条特定的记录进行锁定。
(二)间隙锁
当查询条件是一个范围,例如 id
在 2
到 5
之间时,加的也是记录锁,但锁定的是这个范围内的多条记录,即 2
、3
、4
、5
。这里可能有人会好奇,如果查询的范围里有不存在的记录,比如查 2
到 3
之间,但实际上这之间没有记录,这种情况会不会加锁呢?答案是肯定的。这种针对不存在记录加的锁叫做间隙锁,它也是行锁的一种。间隙锁的作用主要是防止幻读。想象一下,在同一个事务中,刚开始读取数据时某个范围是空的,如果不加间隙锁,其他事务在这个间隙中插入了数据,那么再次读取时结果就会不一样,这在数据库中是不被允许的,而间隙锁就能避免这种情况发生。
(三)临键锁
临键锁是记录锁和间隙锁的组合。当范围查询既涉及到有记录的 id
,又涉及到没有记录的 id
时,就会同时加上记录锁和间隙锁,形成临键锁。
需要注意的是,行锁的正常工作依赖于索引。如果索引不存在,问题可就大了,行锁会直接升级为表锁,把整个表都锁住。这样一来,其他涉及这个表修改的事务都会被阻塞,进而产生各种慢日志,导致数据库连接超时、接口响应超时,甚至网关也会超时,严重影响系统的正常运行。
数据库中的表锁和行锁在保证数据一致性和并发控制方面起着关键作用。了解它们的工作原理和适用场景,不仅能帮助我们在面试中脱颖而出,更能在实际开发中优化数据库性能。要是你对这部分内容还有疑问,欢迎在评论区留言,咱们一起讨论!