假设我有一个存储在 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 来破坏数据库。试图处理两个移动并有效地尝试插入元组 (0, 3, "d4") 和 (0, 3, "Nf3"),两者都具有相同的 move_id,从而破坏了 move_id 的唯一性。
确保唯一性的最佳惯用方式是什么?我想到的一种可能性是让我的 C++ 代码包含一个互斥锁列表,每个游戏一个互斥锁。当 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 的行已经存在,它将被忽略。
有没有更好的方法来做到这一点?我的数据库模式对于我正在尝试做的事情是否合理?