MySQL InnoDB update锁表问题Record Locks

最近做的项目中出现了锁表的问题,导致表无法进行事务(DML)操作,经过排查发现,我们项目中的购物车表有个字段cart_id为uuid类型,并且未设置索引,这里的场景是根据cart_id进行更新内容,Mysql InnoDB行锁不使用索引锁表的时候会锁整张表。

通过命令查询锁日志找到相关锁的sql语句:

show engine innodb status;


mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 485176, OS thread handle 140383913969408, query id 12481371 222.93.77.61 root updating
UPDATE `o_cart_detail` SET MODIFY_TIME = now() WHERE (`cart_id`='1')
------- TRX HAS BEEN WAITING 28 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 2655 page no 4 n bits 144 index PRIMARY of table `o_cart_detail` trx id 5518915 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 15; compact format; info bits 0

通过执行计划分析sql语句:

通过执行计划来看,更新语句并未使用到索引。并且where条件的字段是非索引字段,此时的更新操作是全表锁。

此时我们的修改方案是先进行cart_id字段添加索引,保证业务正常进行。

添加非唯一索引后。再次进行执行计划分析sql语句。此时锁定的记录行从2058 ->  55;此时的更新操作是行锁。

当然最好还是使用唯一索引进行DML操作。

总结:InnoDB 的锁,与索引类型,事务的隔离级别相关。InnoDB 到底是行锁还是表锁取决于你的 SQL 语句。如果查询没有命中索引,也将退化为表锁。InnoDB 的行锁是实现在索引上的,而不是锁在物理行记录上。所以如果访问没有命中索引,也无法使用行锁,将要退化为表锁

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_夜半钟声到客船

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值