Использование таблицы для хранения последнего использованного идентификатора в ферме веб-серверов - PullRequest
1 голос
/ 23 февраля 2009

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

Ответы [ 6 ]

2 голосов
/ 23 февраля 2009

Вы собираетесь использовать ферму серверов для базы данных? Это не звучит "правильно".

Возможно, вы захотите использовать GUID для идентификаторов. Они могут быть большими, но у них нет дубликатов.

С единственным значением "следующий идентификатор" вы столкнетесь с конфликтом блокировок для этой записи. В прошлом я использовал таблицу диапазонов идентификаторов (RangeId, RangeFrom, RangeTo). Таблица диапазонов имеет первичный ключ «RangeId», который является простым числом (например, от 1 до 100). Процедура «получить следующий идентификатор» выбирает случайное число от 1 до 100, получает первую запись диапазона с идентификатором ниже, чем случайное число. Это распределяет блокировки по N записям. Вы можете использовать 10, 100 или 1000 записей диапазона. Когда диапазон полностью используется, просто удалите запись диапазона.

Если вы действительно используете несколько баз данных, вы можете вручную убедиться, что набор диапазонов каждой базы данных не перекрывается.

1 голос
/ 23 февраля 2009

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

1 голос
/ 23 февраля 2009

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

Вы можете сделать это в C #, используя оператор блокировки вокруг вашего кода, который обращается к таблице, или в вашей базе данных вы можете собрать транзакцию для чтения / записи. Я не знаю точный синтаксис этого в MySQL.

0 голосов
/ 21 октября 2009

Предполагая, что ваша база данных настроена для работы с изоляцией транзакции READ_COMMITTED или лучше, затем используйте одну инструкцию SQL, которая обновляет строку, устанавливая для нее старое значение, выбранное из строки, плюс приращение. При более низких уровнях изоляции транзакций может потребоваться использовать INSERT в сочетании с SELECT FOR UPDATE.

Как отметил [Аарон Дигулла], лучше распределять блоки идентификаторов, чтобы уменьшить количество запросов и блокировку таблиц.

Приложение должно выполнить получение идентификатора в отдельной транзакции от любой бизнес-логики, в противном случае любая транзакция, для которой требуется идентификатор, в конечном итоге будет ожидать каждой транзакции, которая сначала запрашивает идентификатор для фиксации / отката.

В этой статье: http://www.ddj.com/architect/184415770 объясняется стратегия HIGH-LOW, которая позволяет вашему приложению получать идентификаторы от нескольких распределителей. Несколько распределителей улучшают параллелизм, надежность и масштабируемость.

Здесь также идет длинное обсуждение: http://www.theserverside.com/patterns/thread.tss?thread_id=4228 "HIGH / LOW Генератор идентификаторов объектов Singleton + Session Bean"

0 голосов
/ 23 февраля 2009

AFAIK единственный способ получить это из БД с красиво увеличивающимися числами - это транзакционные блокировки в БД, что является ужасной производительностью. Вы можете получить поведение без блокировки, используя GUID, но, честно говоря, вы будете сталкиваться с требованиями транзакций в каждой операции CRUD, о которой вы можете подумать в любом случае.

0 голосов
/ 23 февраля 2009

Если у вас проблемы с производительностью, увеличьте ID на 100 и используйте поток для каждого «клиентского» сервера. Поток должен делать приращение и вручать каждой заинтересованной стороне новый идентификатор. Таким образом, потоку требуется только один раз получить доступ к БД для 100 идентификаторов.

В случае сбоя потока вы потеряете пару идентификаторов, но если это не происходит постоянно, вам не нужно об этом беспокоиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...