数据库的表锁、行锁

讲讲数据库的表锁、行锁

可能在日常的开发过程中有的小伙伴没有注意会用到数据库的表锁、行锁。举个简单的例子:更新数据update,数据库就会默认开启事务,然后根据where条件来加锁,一般默认的都是加的是行锁。如果我们有一个正在更新的操作,那么其他的更新请求是进不来的,主要就是为了防止修改的过程中有其他的事务来修改同一条记录,造成脏数据,这个时候用的就是行锁。再比如说修改表结构,修改一个字段的名称,或者是修改它的类型,那么mysql就会把当前的表锁住,所有关于这个表的其他事务的增删改查都进不来,都得等着,只有修改完成之后,释放了表锁才能让它进来。这个时候就是把整个表锁住,加的是表锁,那么表锁锁的范围比较广,所以日常的比如说修改了表的结构,字段的名称,或者是类型,我们要往生产环境同步的时候就要注意,一般都是等到凌晨夜里面来操作,因为人少嘛,相对来讲影响就会小很多。这个是表锁。

表锁、行锁这两个基础的概念还是很好理解的,针对的是锁的粒度,或者说是锁的范围。那么再往下细分的话,行锁相对表锁来说,就要稍微复杂一些了。还是刚才的例子,更新数据,如果你的where条件里面匹配的是索引,比如说主键索引ID,ID等于1,这个时候就会把ID等于1这条记录加一个锁,叫记录锁(当然这个也是行锁,行锁里面的一种叫记录锁,只是针对当前的记录加的锁),那么如果查询的条件是索引的范围,比如说这个ID,在2到5之间,那么加的也是记录锁,只是它不止一条,是好几条2 3 4 5。这个时候,可能有小伙伴会问了,如果我查这个2 3不存在,或者某一条记录不存在。它是不是也会加锁,那答案是肯定的,如果没有记录的话,照样会加锁,名字也很直观,它叫间隙锁,属于行锁的一种,专门用于对一些不存在的记录进行加锁。加锁的目的主要是为了防止幻读。如果在同一个事务里面,一开始读到的数据是空的,如果不加锁的话,其他的事务又往这个空隙增加了一个数据,那么我们再次读的时候,就会造成两个结果不一样,这种情况在数据库里面叫做幻读,这个是InnoDB不允许的。然后行锁里面,还有临键锁就是记录锁跟间隙锁的组合,如果范围查询里面既涉及到了有记录的ID,又涉及到了没有记录的ID,那么就是记录锁跟间隙锁的组合锁,两个一起加。

所以说总结下来,行锁也就是三种:记录锁、间隙锁、临键锁,当然这些都是基于索引的,如果你的索引不存在,那就麻烦了,会直接升级为表锁。锁住整个表,那么其他的事务,只要涉及到这个表的修改都会被阻塞,会产生各种的慢日志,然后是数据库连接超时,接口响应超时,网络超时等等一系列的反应(千万别做这个大怨种)(完)

ps: 如果有任何疑问,欢迎评论区给我留言


已有 0 条评论

    感谢参与互动!