5

我正在开发一个在线多人棋盘游戏并且有一个 SQL 服务器问题。

让我们假设游戏允许两个玩家。创建游戏时,创建者被添加为第一个用户。

此时,两个用户可以尝试同时加入游戏。这些用户之一应该被阻止。

我的数据库架构如下:

tbGame - contains a list of all games. PrimaryKey is GameId
tbPlayers - contains a list of all registered users. PrimaryKey is PlayerId
tbPlayersInGame - contains a list of all players in each game. Foreign key 
                  relations to tbGame and tbPlayers.

我觉得我需要两件事:

  1. 一种基于 GameId 锁定 tbPlayersInGame 的方法。这将在将玩家添加到游戏时使用。从我读过的内容来看,这听起来像是一个键范围锁(在 GameId 上)是合适的。
  2. 一种强制 1 对 2 关系的方法,这样尝试添加第三个玩家就会失败。
4

2 回答 2

1

几个建议:

1)当您尝试写入 tbPlayersInGame 表时,首先执行 SELECT 以确保游戏未满,然后 INSERT INTO 表。将此 SELECT 和 INSERT INTO 包装在事务隔离级别设置为可序列化的事务中。

2)没有单独的tbPlayersInGame表,而是在tbGame中有2个字段:Player1Id,Player2Id

于 2011-10-17T23:41:13.173 回答
1

您可以将表设置为必须包含列,而不是 1 对 n 关系 - 可能标记为host_playerand visitor_player,或必要的等价物(如国际象棋中的blackand white)。这样做的好处是将有趣的事情降到最低限度,并显示关系的自然状态。

这当然只有在玩家数量永久有限的情况下才有效 - 对于大多数棋盘游戏实例,这可能会很好......

如果您尝试制作上限可变的游戏(无论出于何种原因),您可以使用以下语句“检测”可用的空闲插槽:

INSERT INTO game_players (game_id, player_id) 
SELECT VALUES (:GAME_ID, :PLAYER_ID)
WHERE :MAX_PLAYER_COUNT > (SELECT COUNT(*)
                           FROM game_players
                           WHERE game_id = :GAME_ID)

如果您返回错误代码 100(“未选择/更新任何行),则播放器列表已满。您可能需要添加其他条件(以防止玩家加入两次),但这个概念应该仍然有效。

于 2011-10-17T23:48:38.610 回答