MySQL的存储引擎是InnoDB时 for update有行锁和表锁。
用法:
select ... for update
注意点
- 仅适用于InnoDB,必须在事务块 begin/commit中才有效
- 当有明确的主键/索引时是行级别的锁,否则是表级别的锁
验证
数据库表如下
id是主键,name有索引,age和createtime无索引
验证1(有明确的主键/索引是是行级别的锁)
Terminal 1 执行
begin;
select * from bintest.afs_test a where a.name='HELLO01' for update;
Termianl 2 执行
update afs_test a set a.name = 'HELLO02' where a.name = 'HELLO020';
该update会被正确执行,name被更改,说明表没有被锁
再执行
update afs_test a set a.name = 'HELLO010' where a.name = 'HELLO01';
这时Terminal2会被block知道Terminal 1执行 commit或者Terminal 2等待超时。
说明当Terminal 1对有索引的name执行查询for update是对行级别的锁
验证2(无明确主键/索引的是表级别的锁)
Terminal 1 执行
begin;
select * from afs_test a where a.age = 20 for update;
Terminal 2 执行
update afs_test a set a.age = a.age+5 where a.age=23;
age是无索引的,Terminal 2更新age=23的记录,与Terminal 1的查询age=20无行记录重合。但Terminal 2的执行会被block,知道Terminal 1执行 commit或者Terminal 2等待超时。说明对无明确主键/索引的是表级别的锁。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。