如何防止多个同步SQL更新到国际象棋游戏

时间:2012-12-14 09:50:43

标签: sql database postgresql chess

假设我有一个国际象棋游戏存储在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的行已经存在且它将是忽略。

有更好的方法吗?我的数据库架构对于我想要做的事情是否合理?

2 个答案:

答案 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