teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

訂正

2017/06/01 13:26

投稿

mpyw
mpyw

スコア5223

answer CHANGED
@@ -12,6 +12,6 @@
12
12
 
13
13
  ユーザBによる挿入処理(重複orユニーク制約により失敗)
14
14
 
15
- SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。
15
+ SELECT ... FOR UPDATE でロックをかけながら行選択すると、存在しなかった場合には他のリクエストによるテーブルへの挿入処理およびその未存在のレコードに対する選択処理がブロックされるので、このやり方でも安全性を担保することはできます。ただしパフォーマンスは低下する可能性があるので、ロックせずにSELECTし、「万が一競合したらユニーク制約のエラーに拾ってもらう」というやり方でもいいです。
16
16
 
17
17
 

1

補足

2017/06/01 13:26

投稿

mpyw
mpyw

スコア5223

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