凡事都在事上磨,这样才能精进,成长进步提高! ------ 博客园首页

update未走索引导致全表锁住

事件经过:
前段时间, 自动化测试的小姐姐向我们开发人员反应, 由于我方经常debug导致锁表, 她们的用例经常失败.
该问题出现的时机基本一致,通过show OPEN TABLES where In_use > 0;以及show processlist, 确定sql.
但是奇怪的是这次的事故竟然是把整个表锁了, 而不是以往只是某条数据被锁住(开发和测试未单独分库, 调试时的某些数据偶尔会导致锁表情况).
对sql进行分析后发现, 这条update后面的where竟然没有走索引!!!

原因:
我们使用mysql时一般使用的都是默认引擎innoDB.
而innoDB的行锁是通过给索引上的索引项枷锁来实现的, 而不是针对记录来加锁的.
假如在操作数据的时候, 没有索引, 是无法使用行级锁的, 此时使用的是表锁. (小伙伴们这下明白对mysql来说索引多重要了吧)

引申
同时引申一个有趣的现象. 假如多个线程操作的是不同数据, 也用了索引, 但是为什么还是锁表了呢?
原因还是上面这个, 行锁是在索引上的. 假如你where条件后面分别是: code=“001” and name=“xx” 和code=“001” and name=“yy”, 索引在code上, 那么还是会出现锁表的.
例如:
tdb_goods 表中brand_name上有索引, 而goods_price字段无索引

在线程A中执行
START TRANSACTION;
UPDATE tdb_goods SET is_show=1 WHERE brand_name='苹果' AND goods_price='3388.000';
然后在A执行COMMIT;之前在另一个线程B中开启一个事务并执行UPDATE tdb_goods SET is_show=1 WHERE brand_name='苹果' AND goods_price='2288.000';
此时线程Bmysql会提示:
错误代码: 1205
Lock wait timeout exceeded; try restarting transaction
1
2
3
4
5
6
7
那么
另外需要注意一点: 如果表比较小, 即使有索引, mysql也不一定会走索引而是查全表.
————————————————
版权声明:本文为CSDN博主「yytoo2」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yytoo2/article/details/107557246

因为相信,所以看见.
posted @ 2021-06-03 10:30  zeenzhou  阅读(42)  评论(0编辑  收藏  举报