问题描述
这种情况下,可能会影响其他事务的并发性能,从而降低系统的稳定性和效率。
举例来说,假设我们有一个名为setmeal_dish的表,其结构如下:
create table setmeal_dish
(
id bigint auto_increment comment '主键'
primary key,
setmeal_id bigint null comment '套餐id',
dish_id bigint null comment '菜品id',
name varchar(32) null comment '菜品名称 (冗余字段)',
price decimal(10, 2) null comment '菜品单价(冗余字段)',
copies int null comment '菜品份数'
)
comment '套餐菜品关系' collate = utf8_bin;
现在,假设我们开启了两个事务,事务1执行了删除操作,而事务2执行了更新操作。事务1的删除操作没有基于索引字段,而事务2的更新操作由于表级锁的缘故无法执行。
解决思路
通过为非索引字段添加索引,我们可以避免InnoDB使用表级锁,从而提高数据库的并发性能。这样,即使在删除操作时,也能保持数据库表的行级锁,确保其他事务可以正常执行,提高系统的稳定性和性能。
create index setmeal_dish_dish_id_index
on setmeal_dish (dish_id);
再次测试
在添加索引后,再次进行相同的删除和更新操作
总结:没有命中索引的查询更新语句会加什么锁,跟命中索引的语句有什么不同?
简:InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。所以如果访问没有命中索引,就无法使用行锁,将要退化为表锁。
共享行锁上升为共享表锁,排他行锁上升为排他表锁。加表锁之前会检查意向排他锁来判断当前是否存在排他行锁,如果存在则需要阻塞等待排他行锁的释放,否则可以直接获得表锁。