次のようなスキーマを持つ SQL データベースに格納されたチェスのゲームがあるとします。
CREATE TABLE chessgames(
game_id INTEGER,
move_id INTEGER,
move char(4)
};
したがって、game_id が 0 の進行中のゲームで手が e4 e5 の場合、テーブルには (0, 1, "e4") と (0, 2, "e5") のタプルが含まれます。
ここで、クライアントが move d4 と Nf3 の両方を同時に送信してデータベースを破壊しようとしたとします。2 つの Move を処理しようとして、(0, 3, "d4") と (0, 3, "Nf3") のタプルを効果的に挿入しようとしていますが、どちらも同じ move_id で、move_id の一意性を壊しています。
一意性を確保するための最も慣用的な方法は何ですか? 私が思いついた 1 つの可能性は、C++ コードにミューテックスのリスト (ゲームごとに 1 つのミューテックス) を含めることです。d4 などの移動が到着すると、C++ コードは対応するゲームのミューテックスをロックし、次の SQL クエリを実行します。
SELECT move_id, move FROM chessgames WHERE game_id = 0
ゲームのすべての動きを取得するために (私が示した例では、これは e4 と e5 になります)、C++ コードはそれらの動きを取得し、どの行にもまだ move_id = 3 がないことを確認してから、現在の位置を構築するために動きを実行します。移動d4が有効であることを確認できること。有効な場合は実行されます
INSERT INTO chessgames VALUES (0, 3, "d4")
移動をデータベースに保存してから、ミューテックスを解放します。
このように、Nf3 移動が d4 移動処理と同時に到着した場合、ロックされたミューテックスによってブロックされ、Nf3 が最終的に処理されると、move_id = 3 の行が既に存在することがわかり、無視されます。
これを行うより良い方法はありますか?私のデータベーススキーマは、私がやろうとしていることに対して合理的ですか?