4.
ロックおさらい(簡易)
• 共有ロック(LOCK_S)
共有ロック同士は互いにブロックしない
例:SELECT LOCK IN SHARE MODE
• 排他ロック(LOCK_X)
何も受け付けないぞ、排他
例:INSERT(成功), UPDATE, DELETE,
SELECT FOR UPDATE
X S
X Conflict Conflict
S Conflict Compatible
4
大きく分けてロックは2種類
5.
5
> BEGIN;
> SELECT * FROM player
WHERE id = 100
LOCK IN SHARE MODE;
> BEGIN;
トランザクションA トランザクションB
共有と排他順によるデッドロック例
6.
6
> BEGIN;
> SELECT * FROM player
WHERE id = 100
LOCK IN SHARE MODE;
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
Player.id(100)に
共有ロックが取られてるため、
待たされる
トランザクションA トランザクションB
共有と排他順によるデッドロック例
待たされる
7.
7
> BEGIN;
> SELECT * FROM player
WHERE id = 100
LOCK IN SHARE MODE;
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
DeadLock !!! Player.id(100)に
共有ロックが取られてるため、
待たされる排他->共有ロックなら
デッドロックにならない
トランザクションA トランザクションB
共有と排他順によるデッドロック例
待たされる
9.
テーブル定義の例
key Extra
id PRIMARY AUTO-INCR
player KEY-INDEX
item KEY-INDEX
key Extra
id PRIMARY AUTO-INCR
key Extra
id PRIMARY
Player
Item
PlayerItem
外部キー制約する側(子)
9
外部キー制約される側(親)
11.
> BEGIN;
> INSERT INTO player_item
(player,item) VALUES(100, 2000);
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
トランザクションA トランザクションB
11
外部キー制約により、
Player.id(100), Item.id(2000)
に対して共有ロックを獲得
Player.id(100)に
共有ロックが取られてるため、
待たされる
外部キーで共有ロックがかかるのを確認
>
待たされる
12.
12
> BEGIN; > BEGIN;
> UPDATE player SET XXX = YYY
WHERE id = 100;
DeadLock !!!
共有->排他順によるデッドロック例(外部キーver)
トランザクションA トランザクションB
> INSERT INTO player_item
(player,item) VALUES(100, 2000);
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
Player.id(100)に
共有ロックが取られてるため、
待たされる
待たされる
16.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
トランザクションA トランザクションB
16
case1:item -> player の順でindex定義
17.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
> INSERT INTO player_item
(player,item) VALUES(100,2000);
トランザクションA トランザクションB
17
• Player.id(100)に排他ロックが
取られてるため待たされる
• シャドーロックでitem.id(2000)に
対して共有ロック獲得済み
case1:item -> player の順でindex定義
待たされる
18.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
> INSERT INTO player_item
(player,item) VALUES(100,2000);
トランザクションA トランザクションB
18
• Player.id(100)に排他ロックが
取られてるため待たされる
• シャドーロックでitem.id(2000)に
対して共有ロック獲得済み
case1:item -> player の順でindex定義
待たされる
> SELECT * FROM item
WHERE id = 2000 FOR UPDATE;
DeadLock !!!
19.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
19
case2:player -> item の順でindex定義
トランザクションA トランザクションB
20.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
> INSERT INTO player_item
(player,item) VALUES(100,2000);
20
• Player.id(100)に排他ロックが
取られてるため待たされる
• item.id(2000)に対しては
共有ロックを取ってない
(取る前にPlayer.idで止まった)
case2:player -> item の順でindex定義
トランザクションA トランザクションB
待たされる
21.
> BEGIN;
> SELECT * FROM player
WHERE id = 100 FOR UPDATE;
> BEGIN;
> INSERT INTO player_item
(player,item) VALUES(100,2000);
> SELECT * FROM item
WHERE id = 2000 FOR UPDATE;
21
>
待たされない!
• Player.id(100)に排他ロックが
取られてるため待たされる
• item.id(2000)に対しては
共有ロックを取ってない
(取る前にPlayer.idで止まった)
case2:player -> item の順でindex定義
トランザクションA トランザクションB
待たされる
Be the first to comment