mysql for updateロックタイプ探索
3332 ワード
mysql for updateロックのタイプテーブル構造をいくつかの実験で探索した.
きろく
参照
insert into `test_user`(`id`,`login_name`,`name`)values('1','zhangsan','張三');
insert into `test_user`(`id`,`login_name`,`name`)values('2','lisi','李四');
実験1セッション_1
session_2
実験2セッション_1
session_2
実験1と実験2から,唯一のインデックスがある列に対してselect for updateは排他ロック,行レベルロックを加えていることが分かった.ロック後、他の行に対してfor updateのクエリー実験3 session_1
session_2
session_1
session_2
実験4セッション_1
session_2
実験3と実験4から,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文は空レコードに共有ロックを加え,このとき他のスレッドは挿入できず,クエリー操作が可能であることが分かった.既存のレコードにロックがかかっていない場合、他のスレッドはレコードを変更できます.