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)操作一致性:当需要执行大规模数据操作(例如,更新表的大部分数据)时,使用表级锁可以确保整个操作是一致的,因为整个表都被锁定,不会发生部分数据被更新而其他部分未更新的情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」