select * from table for update使用行锁还是表锁,主要看是否使用到索引或主键,如果没有使用到索引或主键,则使用了表锁,如果使用到索引或主键,则是行锁
创建表
//id为主键
//name 为唯一索引
CREATE TABLE `user` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`name` VARCHAR ( 255 ) DEFAULT NULL,
`age` INT ( 11 ) DEFAULT NULL,
`code` VARCHAR ( 255 ) DEFAULT NULL,
PRIMARY KEY ( `id` ),
KEY `idx_age` ( `age` ) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 1570068 DEFAULT CHARSET = utf8
行锁
使用主键或索引,select * from table for update使用行锁
select * from user where id=1 for update
select * from user where name='zhangsan' for update
在执行select的同时开启事务,不提交事务,执行以下一条sql
update user set age=20 where id=1;
update user set age=20 where name='zhangsan';
会被阻塞一直无法更新数据,但是执行
update user set age=20 where id=2;
却是成功的,说明只阻塞了id=1或name=‘zhangsan’的行数据,所以是行锁
表锁
未使用索引或主键时,select * from table for update使用表锁
select * from user where code='abc' for update
执行sql前开启事务,不提交事务继续执行
update user set age=20 where id=2;
update user set age=18 where id=1;
会被阻塞无法更新数据
结果
如果查询条件用了索引或主键,那么select … for update就会进行行锁。
如果是普通字段(没有索引或主键),那么select … for update就会进行锁表。