mysql for updateロックタイプ探索

3332 ワード

mysql for updateロックのタイプテーブル構造をいくつかの実験で探索した.
CREATE TABLE `test_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `login_name` varchar(20) NOT NULL DEFAULT '',
  `name` varchar(30) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_login_name` (`login_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4

きろく
参照
insert into `test_user`(`id`,`login_name`,`name`)values('1','zhangsan','張三');
insert into `test_user`(`id`,`login_name`,`name`)values('2','lisi','李四');
実験1セッション_1
begin;
select * from test_user where login_name = 'zhangsan' for update;

+----+------------+--------+
| id | login_name | name   |
+----+------------+--------+
|  1 | zhangsan   |      |
+----+------------+--------+

session_2
begin;
select * from test_user where login_name = 'zhangsan' for update;

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

実験2セッション_1
begin;
select * from test_user where login_name = 'zhangsan' for update;
+----+------------+--------+
| id | login_name | name   |
+----+------------+--------+
|  1 | zhangsan   |      |
+----+------------+--------+
1 row in set (0.00 sec)

session_2
select * from test_user where login_name = 'lisi' for update;
+----+------------+--------+
| id | login_name | name   |
+----+------------+--------+
|  2 | lisi       |      |
+----+------------+--------+
1 row in set (0.00 sec)

実験1と実験2から,唯一のインデックスがある列に対してselect for updateは排他ロック,行レベルロックを加えていることが分かった.ロック後、他の行に対してfor updateのクエリー実験3 session_1
begin;
select * from test_user where login_name = 'bucunzai' for update;
Empty set (0.00 sec)

session_2
begin;
select * from test_user where login_name = 'bu4' for update;
Empty set (0.00 sec)

insert into test_user (login_name,name) values ('bu4','bu2name');
    

session_1
commit;
  

session_2
Query OK, 1 row affected (20.62 sec)
    

実験4セッション_1
begin;
select * from test_user where login_name = 'bucunzai' for update;
Empty set (0.00 sec)

session_2
select * from test_user where login_name = 'zhangsan' for update;

+----+------------+--------+
| id | login_name | name   |
+----+------------+--------+
|  1 | zhangsan   |      |
+----+------------+--------+
1 row in set (0.00 sec)

update test_user set name = '   ' where login_name = 'zhangsan'; 
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

実験3と実験4から,for update文は空レコードに共有ロックを加え,このとき他のスレッドは挿入できず,クエリー操作が可能であることが分かった.既存のレコードにロックがかかっていない場合、他のスレッドはレコードを変更できます.