前几天,有个表锁表了。
数据库是ORACLE,执行的语句是:
select * from t1 where a=1 for update;
update t1 set a =2 where a =1;
执行这两个语句的时候,一个是锁表,一个是误操作。
经过查询,mysql的说法比较奇怪:
当执行的时候显式指定主键,则锁主键;如果没有指定主键,如果是二级索引,那么锁一定范围的数据。
如果没有索引,则锁全表。
然后,逻辑上:如果是INNODB模式,肯定会维护一个主键索引。
也就是说:
当执行
select * from t1 where a=‘张’ for update;
的时候,由于不是主键,所以基本上会锁一定范围的数据。如果没有索引或者不走索引,锁全表。
ORACLE基本上也是一样的:如果不指定主键则锁全表。
如果是二级索引,那么锁一定范围的数据。
如果是主键,只锁指定行。
没有查到该条数据,则不锁表。
但是很明显:按照现在常规数据库的规范,一般都是自增索引,或者说是无意义的索引(不要用有意义的值当键值),所以基本上不会以主键进行筛选。因为没有实际意义。
最好的情况也是二级索引锁范围(似乎是间隙锁)
锁全表的话:
无法进行新增或者更新操作,所有新增和更新会等待锁释放。
所以会影响正常事务的运行。
第二个问题:
执行命令的时候,会断网导致没有上传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;
然后,这个事务就挂着事务把全表给锁了。
第三个问题:修改不停修改的数据。
这个是有很高风险的。
一个是:UPDATE会锁INSERT和UPDATE两个语句,而不是单锁UPDATE。
如果说UPDATE的时候按照二级主键进行加锁,而数据一个在表头一个在表位,或者新增的数据正好在间隙之间,就会锁表。
版权声明:本文为weixin_45642669原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。