MySql哪些情况会导致行锁升级为表锁

一、行锁和表级锁的区别:

行锁:开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高。仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作
表锁:开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度低。直接锁定整张表,在锁定期间,其它进程无法对该表进行写操作。如果是写锁,则其它进程则读也不允许。表锁分为读锁(共享锁(shared lock),针对同一份数据,多个读操作可以同时进行而不会互相影响(select))和写锁(排他锁(exclusive lock),在当前操作没完成之前,会阻塞其它读和写操作(update、insert、delete))

InnoDB 引擎支持行锁和表锁,而 MyISAM 引擎只支持表锁。
MySQL服务器层并没有实现行锁机制,行级锁只在存储引擎层实现。
InnoDB 的行锁是实现在索引上的,而不是锁在物理行记录上。也就是说,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。
例如:

t_user(uid, uname, age, sex) innodb; uid PK,无其他索引
update t_user set age=10 where uid=1; 命中索引,行锁。
update t_user set age=10 where uid != 1; 未命中索引,表锁。
update t_user set age=10 where name='chackca'; 无索引,表锁。

总结:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

二、以下情况会导致行锁升级为表锁:

1、对应的存储引擎没有行级锁(例如:MyIASM)

2、使用LOCK TABLES语句手动锁定表时,MySQL将锁定整个表以确保其他会话不能访问它。

3、类型转换

检索值的数据类型与索引字段不同,虽然MySQL能够进行数据类型转换,但却不会使用索引,从而导致InnoDB使用表锁。通过用explain检查两条SQL的执行计划,可以清楚地看到了这一点。(数据库类型为varchar时 查询用 数字类型时用不了索引 。但数据库类型为int、datetime时 查询类型为字符串,也可以走索引)

4、即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,也会自动升级为表锁

5、当执行 DDL (使用ALTER TABLE、TRUNCATE TABLE等)语句去修改表结构时,会使用表级锁。

6、在查询或更新操作中,如果涉及到大部分数据(占全表的80%或更多),通常会使用表级锁,而不是行级锁。使用表级锁的原因包括以下几点:

1)效率考虑:当涉及大量数据时,使用行级锁可能导致大量的锁竞争和锁粒度的细化,这会影响性能,因为每个被锁定的行都需要维护锁状态。表级锁的粒度更大,因此更高效。

2)简化锁管理:管理大量行级锁可能会导致锁管理的复杂性增加,因为需要跟踪和管理大量锁对象。表级锁更容易管理,因为只有一个锁对象。

3)避免死锁:行级锁可能导致死锁问题的发生,因为大量的锁定请求可能形成复杂的锁依赖关系。表级锁可以降低死锁风险。

4)操作一致性:当需要执行大规模数据操作(例如,更新表的大部分数据)时,使用表级锁可以确保整个操作是一致的,因为整个表都被锁定,不会发生部分数据被更新而其他部分未更新的情况。

posted @   李若盛开  阅读(1279)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示