2009-11-12 84 views
4

应用说明MySQL的 - 表锁定VS行锁定

我有一个存储的ID代表在地图上区域的表。每个地图包含1000个区域。 一个地区是一个地图的任何数量的地区的触摸。用户争夺地图不同区域的所有权。

数据库设计

目前,我有地图,表格,领土的一张桌子和地区的表。

tblMaps: MapID, MapName 

tblTerritories: TerrID (unique game wide), MapID, OwnerID, Status, Modified 

tblAreas: AreaID (1-1000), TerrID 

此刻tblAreas只在地图内存储占用区域 - 不管是否有人拥有它,它不包含每个地图1000条记录。

当用户试图获取某些区域的所有权时,应用程序必须加入这三个表格并查询该地图内的所有拍摄区域。如果其中任何一个被采纳,它应该拒绝他的所有权尝试。如果所有区域都空闲,应创建一个新的区域,并在tblAreas中添加相关区域。

问题

我意识到我需要一个基于事务的系统,使两个用户不能在同一时间尝试“自己”的区域。现在据我所见,我必须锁定整个区域表格,查询区域是否空闲,插入新的区域和区域,提交它并解锁表格......或区域表格应包含全部1000每个地图的区域和锁应该应用于该地图的行。

希望有更好的选择,因为据我所见。锁定表格将意味着所有的区域数据在第二秒内无法访问,或者在行锁定时,表格中充满了无用的未占用区域。

+0

我很困惑 - 究竟是什么区域?地图,我明白。地区只是地图的一个细分部分,可以拥有(我认为?)。区域是一组领土吗?或者是一个地区的一组地区? –

+0

对不起,我已编辑它..地图由1000个区域组成。领土是由一个用户拥有的相邻区域的集合。 – Mark

+0

+1好问题... –

回答

1

如果您有关于tblAreas.AreaID的索引,则任何包含WHERE tblAreas.AreaID in (...)的事务都将锁定这些条目的索引。行本身是否存在并不重要。该锁将阻止另一个事务插入这些ID的任何条目。所以我认为你不需要做任何你的建议。只要查询是否所有区域都可用于您的领土,您将获得以原子方式插入您的领土所需的锁定。

这可能有点问题,因为您的区域ID在游戏范围内并不是唯一的,所以在不同地图中具有相同ID的区域之间可能存在一些虚假的序列化。将mapID添加到您的tblAreas表中可能会有所帮助,因此您可以改为查找(mapID,areaID)索引,这样可以避免索引上出现错误的冲突。 (这会使您的模式非规范化,您可能不想为其他原因而执行此操作。)

+0

难道我不只是锁定tblTerritories中的mapID以阻止任何人插入新条目?非规范化非常诱人......它可以使查询可用区域变得更容易(只需查询tblarea,而不是将三个表连接在一起)......但我认为效率会更低。你怎么看? – Mark

+0

是的,我猜如果你通过mapID查询tblTerritories,这会阻止其他人在你的交易中插入另一个区域。 –

+0

+1为好答案... –