Генерация последовательных номеров в многопользовательском приложении saas - PullRequest
9 голосов
/ 09 июля 2009

Как люди генерируют целочисленные значения auto_incrementing для конкретного пользователя в типичном приложении saas?

Например, номера счетов для всех счетов конкретного пользователя должны иметь значение auto_incrementing и начинаться с 1. Поле идентификатора рельсов в этом случае не может использоваться, поскольку оно используется всеми пользователями.

Вдобавок ко всему, я мог бы сосчитать все счета пользователя, а затем добавить 1, но кто-нибудь знает какое-нибудь лучшее решение?

Ответы [ 6 ]

4 голосов
/ 09 июля 2009

Типичным решением для любой базы данных отношений может быть таблица типа

user_invoice_numbers (user_id int primary key clustered, last_id int)

и хранимая процедура или запрос SQL, например

update user_invoice_numbers set last_id = last_id + 1 where user_id = @user_id
select last_id from user_invoice_numbers where user_id = @user_id

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

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

1) Исключите процедуру, которую вы используете для получения новых номеров из длительных транзакций. Предположим, что вставка в счет процедура является длительной транзакцией со сложной серверной стороной логика. В этом случае вы сначала получаете новый идентификатор, а затем в отдельной транзакции вставляете новый счет. Если откат последней транзакции будет выполнен, авто-номер не уменьшится. Но user_invoice_numbers не будет заблокирован в течение длительного времени, поэтому многие пользователи одновременно могут вставлять счета-фактуры одновременно

2) Не используйте традиционную транзакционную базу данных для хранения данных с последним идентификатором для каждого пользователя. Когда вам нужно вести простой список ключей и значений, существует множество небольших, но быстрых механизмов базы данных, которые могу сделать эту работу за вас. Список баз данных ключей / значений . Вероятно, memcached является самым популярным. В прошлом я видел проекты, где простые хранилища ключей / значений были реализованы с использованием реестра Windows или даже файловой системы. Существовал каталог, в котором каждое имя файла было ключом, а внутри каждого файла был последний идентификатор. И это грубое решение было все же лучше, чем использование таблицы SQL, потому что блокировки были созданы и выпущены очень быстро и не были вовлечены в объем транзакции.

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

2 голосов
/ 09 июля 2009

Если номера счетов независимы для каждого пользователя / клиента, то кажется, что наличие поля «lastInvoice» в каком-либо постоянном хранилище (например, записи БД), связанного с пользователем, довольно неизбежно. Однако это может привести к некоторой конкуренции за «последний» номер.

Действительно ли имеет значение, если мы отправляем пользователю счета 1, 2, 3 и 5 и никогда не отправляем им счета? 4? Если вы можете немного ослабить требование.

Если требование на самом деле «каждый номер счета должен быть уникальным», тогда мы можем рассмотреть все обычные приемы создания идентификаторов, и они могут быть весьма эффективными.

Обеспечение того, что числа являются последовательными, увеличивает сложность, добавляет ли это пользу для бизнеса?

2 голосов
/ 09 июля 2009

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

1 голос
/ 31 мая 2011

Я только что загрузил драгоценный камень, который должен удовлетворить ваши потребности (на несколько лет лучше, чем никогда!):)

https://github.com/alisyed/sequenceid/

0 голосов
/ 09 ноября 2009

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

0 голосов
/ 09 июля 2009

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

...