回答編集履歴

2

訂正

2017/06/01 13:26

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -26,7 +26,7 @@
26
26
 
27
27
 
28
28
 
29
- SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。
29
+ SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理およびその未存在のレコードに対する選択処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。
30
30
 
31
31
 
32
32
 

1

補足

2017/06/01 13:26

投稿

mpyw
mpyw

スコア5223

test CHANGED
@@ -3,3 +3,33 @@
3
3
 
4
4
 
5
5
  MySQLの場合は外部キー制約とユニークキー制約程度しか付けられないので、「アプリケーション側でバリデーションし、データベース側の制約は万が一のための保険にする」という運用にせざるを得ないです。
6
+
7
+
8
+
9
+ ただし、アプリケーション側でバリデーションする場合は「ほぼ同時にリクエストが飛んできた場合」を考慮する必要があります。以下のように入り交じるケースがあるからです。
10
+
11
+
12
+
13
+ ユーザAによる存在確認
14
+
15
+
16
+
17
+ ユーザBによる存在確認
18
+
19
+
20
+
21
+ ユーザAによる挿入処理(成功)
22
+
23
+
24
+
25
+ ユーザBによる挿入処理(重複orユニーク制約により失敗)
26
+
27
+
28
+
29
+ SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。
30
+
31
+
32
+
33
+
34
+
35
+