表索引情况
- id:主键索引
- name:无索引
- good_id:无索引
- user_id:普通索引
当update语句的where条件使用无索引的good_id字段时
事务A更改good_id=1的字段,但提交:
事务B更改good_id=2的行,发生锁等待:
锁查看:
结果:事务2锁等待
改用有索引的user_id作为where条件
’事务A:
事务B:
结果:事务1和事务2都无需等待,瞬间执行
结论
MySQL在每个事物中的update操作,都会加X锁,当update语句无where条件,或者where条件无索引时,会锁住整张表,导致并发的其他事务即便修改的不是同一行,仍要等待前面事务结束释放锁。
开发建议
我们在开发中,一般在更改某条记录时,为了避免并发下对同一条数据操作造成数据不一致,会按照如下步骤操作
- select ...for update查询,此时在事务结束之前其他事务不能对当前记录进行任何更改操作
- 更改某个字段之后再save保存
- 提交事务
这个步骤是没问题的,但是为了避免操作同一张表的不同记录引起表锁等待,我们需要在select语句的where条件上建立索引,这样锁住的是更改的那一行数据,不会导致其他不相干的事务等待锁。