select * from user where id = 1 for update ;
在MySQL中,使用for update子句可以对查询结果集进行行级锁定,以便在事务中对这些行进行更新或者防止其他事务对这些行进行修改。
当使用for update时,锁定行的方式取决于where中的字段是否具有索引,而不是唯一索引。如果where
条件中的字段具有索引(无论是普通索引还是唯一索引),MySQL将锁定与查询结果集匹配的行,如果where中的字段没有索引MySQL将锁表
创建一张表
其中id是主键,user_name建立索引
create table if not exists user
(
id int auto_increment comment '主键ID'
primary key,
user_name varchar(32) null comment '用户名',
password varchar(64) null comment '密码',
phone varchar(11) null comment '手机号'
);
create index user_user_name_index
on test1.user (user_name);
插入三条数据
INSERT INTO user (id, user_name, password, phone) VALUES (1, '小明', '123', '13123920201');
INSERT INTO user (id, user_name, password, phone) VALUES (2, '小王', '1234', '13123920202');
INSERT INTO user (id, user_name, password, phone) VALUES (3, '小狗', '12345', '13123920203');
begin:表示开启一个事物
commit:表示提交事物
新开3个查询窗口
窗口1
begin;
select * from user where id = 1 for update ;
commit;
窗口2
begin;
select * from user where id = 1 for update ;
commit;
窗口3
begin;
select * from user where id = 2 for update ;
commit;
步骤1: 窗口1执行下面代码
begin;
select * from user where id = 1 for update ;
结果如下
这时id = 1的行应该被锁住了
步骤2: 窗口2执行下面代码
begin;
select * from user where id = 1 for update ;
结果如下,一直在等待
最后报锁超时错误
证明id = 1的行被锁住了
步骤3:
查询id=2的数据
begin;
select * from user where id = 2 for update ;
可以查到结果
说明select * from user where id = 1 for update ;只锁了id = 1的行,id = 2行没有被锁
步骤4:
窗口1执行下面代码
commit;
结果如下
窗口2再执行下面代码
begin;
select * from user where id = 1 for update ;
这时就可以查出结果来了
说明id = 1行锁被释放,窗口2就可以查到结果了
证明唯一索引锁行
窗口1
begin;
select * from user where user_name = '小明' for update ;
窗口2
begin;
select * from user where user_name = '小王' for update ;
证明普通索引时锁行
窗口1:
begin;
select * from user where phone = 13123920201 for update ;
窗口2:
begin;
select * from user where id = 2 for update ;
一直再查询
锁等待超时
证明没索引时锁表