Генерация порядковых номеров в многопользовательском приложении SaaS

Существуют также некоторые интересные статьи о блоге Google Testing, обсуждая, почему одиночный элемент/может быть плохим и является антишаблоном:

9
задан Svante 9 July 2009 в 20:02
поделиться

5 ответов

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

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, потому что блокировки были выпущены и сняты очень быстро и не были вовлечены в объем транзакции.

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

4
ответ дан 4 December 2019 в 21:51
поделиться

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

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

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

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

2
ответ дан 4 December 2019 в 21:51
поделиться

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

2
ответ дан 4 December 2019 в 21:51
поделиться

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

0
ответ дан 4 December 2019 в 21:51
поделиться

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

0
ответ дан 4 December 2019 в 21:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: