for UPDATE导致锁表的问题

锁表

前几天,有个表锁表了。

数据库是ORACLE,执行的语句是:

select * from t1 where a=1 for update;
update t1 set a =2 where a =1;

执行这两个语句的时候,一个是锁表,一个是误操作。

问题所在

  1. 开启了事务,然后执行了select for update强制加锁
  2. 没有及时释放事务,导致这个字段无法被查询
  3. 当无法获得锁的时候,其他的sql会锁定,进入到等待状态

 

不命中索引导致的锁表

经过查询,mysql的说法比较奇怪:

当执行的时候显式指定主键,则锁主键;如果没有指定主键,如果是二级索引,那么锁一定范围的数据。
如果没有索引,则锁全表。

逻辑上:如果是INNODB模式,肯定会维护一个主键索引。

当执行

select * from t1 where a=%张’ for update;

由于不是主键,所以基本上会锁一定范围的数据。如果没有索引或者不走索引,锁全表。

ORACLE基本上也是一样的:

  • 如果不指定主键则锁全表。
  • 如果是二级索引,那么锁一定范围的数据。
  • 如果是主键,只锁指定行。
  • 没有查到该条数据,则不锁表。


 

  • 假如命中的是热点sql或者字典表,问题就大了
  • 如果命中的是多个数据,那么被查询到的的所有数据会被锁
  • 如果是RR级别,会加入间隙锁,插入数据命中这个范围的也会被锁

锁全表的话:
无法进行新增或者更新操作,所有新增和更新会等待锁释放。
所以会影响正常事务的运行。


commit没有及时提交

执行命令的时候,会断网导致没有上传COMMIT或者ROLLBACK

也就是说:当程序执行如下SQL的时候:

start transaction
select * from t1 where a=1 for update;
update t1 set a =2 where a =1;
commit;

由于系统断网,只上传了两个命令:

start transaction
select * from t1 where a=1 for update;

然后,这个事务就挂着事务把全表给锁了。


同时多表联查的select执行update。

这个是有很高风险的。

一个是:UPDATE会锁INSERT和UPDATE两个语句,而不是单锁UPDATE。

如果说UPDATE的时候按照二级主键进行加锁,而数据一个在表头一个在表位,或者新增的数据正好在间隙之间,就会锁表。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值