25. 25
翌週
2019-05-12 13:10:21 0x2b3f75a197002019-05-12 13:10:21 0x2b3f75a19700
*** (1) TRANSACTION:
TRANSACTION 2056616651, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 6 lock struct(s), heap size 1136, 4 row lock(s)
MySQL thread id 151527458, OS thread handle 47340841101056, query id 7830734758
10.0.3.60 user update
INSERT INTO party_member (party_id, player_id, job_no, alive_updated, created) VALUES
(...)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: ...
33. 33
1. BEGIN
2. SELECT * FROM party WHERE id=?
3. バリデーション等
4. SELECT * FROM party WHERE id=? FOR UPDATE
5. INSERT INTO party_member ...
6. SELECT * FROM party_member WHERE party_id=?
7. UPDATE party SET member_count=?
8. COMMIT
パーティー参加
34. 34
● party をロックする前にクエリを実行していた
● SELECT * FROM party_member はロック前のバージョン
になる
● 同じ party に同時に参加しようとすると、 SELECT *
FROM party_member が1つ少ない行を返す
○ member_counter に1つ少ない値をSETしてしまう!!
ロストアップデート
35. 35
/* 3人目 */
BEGIN
...
SELECT party ... FOR UPDATE
INSERT party_member
SELECT party_member ... (3人)
UPDATE party SET member_counter=3
COMMIT
ロストアップデート
/* 4人目 */
BEGIN
...
SELECT party ... FOR UPDATE
(ロック待ち)
.
.
.
INSERT party_member
SELECT party_member ... (3人!!)
UPDATE party SET member_counter=3
COMMIT
36. 36
● BEGIN 直後に SELECT party ... FOR UPDATE する
○ 今は良いけどあとでエンバグしそう🙄
● member_counter = member_counter+1
○ SELECT party_member が減らせる👍
○ いろんな箇所で触っているので保留
解決案(1)