MySQL for update锁表还是锁行校验

select * from user where id = 1 for update ;

1. for update作用

在MySQL中,使用for update子句可以对查询结果集进行行级锁定,以便在事务中对这些行进行更新或者防止其他事务对这些行进行修改。

当使用for update时,锁定行的方式取决于where中的字段是否具有索引,而不是唯一索引。如果where

条件中的字段具有索引(无论是普通索引还是唯一索引),MySQL将锁定与查询结果集匹配的行,如果where中的字段没有索引MySQL将锁表

2. 撸代码证明结果

创建一张表

其中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;

a. 查询带普唯一引字段

步骤1: 窗口1执行下面代码

begin;
select * from user where id = 1 for update ;

结果如下

MySQL for update锁表还是锁行校验_第1张图片

这时id = 1的行应该被锁住了

步骤2: 窗口2执行下面代码

begin;
select * from user where id = 1 for update ;

结果如下,一直在等待

MySQL for update锁表还是锁行校验_第2张图片

最后报锁超时错误

MySQL for update锁表还是锁行校验_第3张图片

证明id = 1的行被锁住了

步骤3:

查询id=2的数据

begin;
select * from user where id = 2 for update ;

可以查到结果

MySQL for update锁表还是锁行校验_第4张图片

说明select * from user where id = 1 for update ;只锁了id = 1的行,id = 2行没有被锁

步骤4:

窗口1执行下面代码

commit;

结果如下

MySQL for update锁表还是锁行校验_第5张图片

窗口2再执行下面代码

begin;
select * from user where id = 1 for update ;

这时就可以查出结果来了

MySQL for update锁表还是锁行校验_第6张图片

说明id = 1行锁被释放,窗口2就可以查到结果了

证明唯一索引锁行

b. 查询带普通索引字段

窗口1

begin;
select * from user where user_name = '小明' for update ;

MySQL for update锁表还是锁行校验_第7张图片

窗口2

begin;
select * from user where user_name = '小王' for update ;

MySQL for update锁表还是锁行校验_第8张图片

证明普通索引时锁行

c. 查询没索引字段

窗口1:

begin;
select * from user where phone = 13123920201 for update ;

MySQL for update锁表还是锁行校验_第9张图片

窗口2:

begin;
select * from user where id = 2 for update ;

MySQL for update锁表还是锁行校验_第10张图片

一直再查询

MySQL for update锁表还是锁行校验_第11张图片

锁等待超时

证明没索引时锁表

你可能感兴趣的:(mysql,数据库,java)