应用说明
我有一张表,其中存储了代表 map 上区域的 ID。每张 map 包含 1000 个区域。 领土是 map 上任意数量的相互接触的区域。用户争夺 map 不同区域的所有权。
数据库设计
目前我有一张 map 表、一张领土表和一张区域表。
tblMaps: MapID, MapName
tblTerritories: TerrID (unique game wide), MapID, OwnerID, Status, Modified
tblAreas: AreaID (1-1000), TerrID
目前 tblAreas 仅存储 map 中的占用区域 - 无论是否有人拥有它,它都不包含每张 map 1000 条记录。
当用户试图取得某些区域的所有权时,应用程序必须连接这三个表并查询该 map 中所有取得的区域。如果其中任何一个被拿走,它应该拒绝他的所有权尝试。如果所有区域都是免费的,则应创建一个新区域并将相关区域添加到 tblAreas 中。
问题
我意识到我需要一个基于交易的系统,这样两个用户就不会试图同时“拥有”该区域。现在据我所知,我必须要么锁定整个 Area 表,查询以查看这些区域是否空闲,插入一个新的领土及其区域,提交并解锁表......或者 Areas 表应该包含所有 1000每个 map 的区域和锁应该只应用于该 map 的行。
希望有更好的选择,因为据我所知。锁定表将意味着在那一秒内所有区域数据都不可访问,或者使用行锁定表充满无用的未占用区域。
最佳答案
如果您在 tblAreas.AreaID 上有一个索引,那么任何包含 WHERE tblAreas.AreaID in (...)
的事务都会锁定这些条目的索引。行本身是否存在并不重要。该锁将阻止另一个事务为这些 ID 插入任何条目。所以我认为你不需要做任何一个建议。只需查询是否所有区域都可用于您的领地,您就可以获得自动插入领地所需的锁。
这可能有点问题,因为您的区域 ID 不是游戏范围内唯一的,因此在不同 map 中具有相同 ID 的区域之间可能存在一些错误的序列化。将 mapID 添加到您的 tblAreas 表可能会有所帮助,这样您就可以创建一个 (mapID, areaID) 索引来查找,这将避免索引上的错误冲突。 (这会使您的模式非规范化,您可能出于其他原因不想这样做。)
关于mySQL - 表锁定与行锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1726129/