事件经过:
前段时间, 自动化测试的小姐姐向我们开发人员反应, 由于我方经常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