mySQL - блокировка таблиц и блокировка строк - PullRequest
4 голосов
/ 13 ноября 2009

Описание применения

У меня есть таблица, в которой хранятся идентификаторы, представляющие области на карте. Каждая карта содержит 1000 областей. Территория - это любое количество областей карты, которые касаются . Пользователи сражаются за владение разными участками карты.

Разработка базы данных

В настоящее время у меня есть таблица карт, таблица территорий и таблица областей.

tblMaps: MapID, MapName

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

tblAreas: AreaID (1-1000), TerrID

В настоящее время tblAreas хранит только занятые области на картах - он не содержит 1000 записей на карту независимо от того, принадлежит ли она кому-либо.

Когда пользователь пытается завладеть некоторыми областями, приложение должно объединить три таблицы и запросить все занятые области на этой карте. Если какой-либо из них будет взят, он должен отклонить его попытку собственности. Если все области свободны, должна быть создана новая территория и соответствующая область добавлена ​​в табличные области.

Задача

Я понял, что мне нужна система на основе транзакций, чтобы два пользователя не пытались «владеть» областью одновременно. Теперь, насколько я вижу, я должен либо заблокировать всю таблицу Area, запросить, свободны ли области, вставить новую территорию и ее области, зафиксировать ее и разблокировать таблицу ... ИЛИ Таблица Areas должна содержать все 1000 области каждой карты и блокировки должны быть применены только к строкам этой карты.

Надеюсь, есть лучший вариант, потому что, насколько я вижу. Блокировка таблицы будет означать, что все данные области недоступны в течение этой секунды, или при блокировке строки таблица заполнена бесполезными незанятыми областями.

1 Ответ

1 голос
/ 13 ноября 2009

Если у вас есть индекс для tblAreas.AreaID, то любая транзакция, включающая WHERE tblAreas.AreaID in (...), заблокирует индекс для этих записей. Не имеет значения, существуют ли сами строки или нет. Эта блокировка не позволит другой транзакции вставить какие-либо записи для этих идентификаторов. Поэтому я не думаю, что вам нужно делать одно из ваших предложений. Просто запросив, доступны ли все области для вашей территории, вы получите замки, необходимые для атомной вставки вашей территории.

Это может быть небольшой проблемой, так как идентификаторы вашей области не являются уникальными для всей игры, поэтому может быть некоторая ложная сериализация между областями с одинаковым идентификатором на разных картах. Это может помочь добавить mapID в вашу таблицу tblAreas, чтобы вы могли вместо этого создать индекс (mapID, areaID) для поиска, чтобы избежать ложных коллизий в индексе. (Это приведет к денормализации вашей схемы, чего вы, возможно, не захотите делать по другим причинам.)

...