假设我有一个国际象棋游戏存储在SQL数据库中,其格式如下:
CREATE TABLE chessgames(
game_id INTEGER,
move_id INTEGER,
move char(4)
};
因此,如果正在进行的游戏(使用game_id 0)有移动e4 e5,那么该表将具有元组(0,1,“e4”)和(0,2,“e5”)。
现在假设客户端试图通过同时发送移动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的行已经存在且它将是忽略。
有更好的方法吗?我的数据库架构对于我想要做的事情是否合理?
答案 0 :(得分:2)
首先,您应该在列game_id和move_id上创建一个UNIQUE索引。 这样,您可以确保数据库级别上每个游戏的move_id唯一性。
CREATE UNIQUE INDEX U_game_move
ON chessgames
(game_id, move_id);
然后,互斥方法很好,但您也可以考虑创建一个触发器来处理move_id递增。
答案 1 :(得分:0)
我了解到我需要的是乐观锁定,就像答案一样 question