Последовательность без пропусков, в которой участвуют несколько транзакций с несколькими таблицами

У меня есть требование (по закону) без пропусков чисел на разных таблицах. У идентификаторов могут быть дыры, но не последовательности.

Это то, что я должен решить в коде C# или в базе данных (Postgres, MS SQL и Oracle).

Это моя проблема:

Start transaction 1

Start transaction 2

Insert row on table "Portfolio" in transaction 1

Get next number in sequence for column Portfolio_Sequence (1)

Insert row on table "Document" in transaction 1

Get next number in sequence for column Document_Sequence (1)

Insert row on table "Portfolio" in transaction 2

Get next number in sequence for column Portfolio_Sequence (2)

Insert row on table "Document" in transaction 2

Get next number in sequence for column Document_Sequence (2)

Problem occurred in transaction 1

Rollback transaction 1

Commit transaction 2

Проблема: разрыв в последовательности для обоих Portfolio_Sequence а также Document_Sequence,

Обратите внимание, что это очень упрощено, и в каждую из транзакций включено больше таблиц.

Как я могу справиться с этим?

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

4 ответа

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

Я бы подумал: а как насчет действия постобработки, когда каждый день у вас есть процесс, который работает в конце рабочего дня, проверяет пробелы и нумерует все, что нужно перенумеровать?

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

Надеюсь, это поможет.

Эту проблему невозможно решить в принципе, потому что любая транзакция может выполнить откат (ошибки, тайм-ауты, взаимные блокировки, сетевые ошибки,...).

У вас будет серийный спор. Постарайтесь максимально сократить количество конфликтов: сделайте транзакцию, которая выделяет номера, как можно меньше. Кроме того, выделите номера как можно позже в транзакции, потому что только после того, как вы выделите номер, возникает конфликт. если вы выполняете 1000 мс безудержной работы, а затем выделяете число (принимая 10 мс), у вас все равно будет степень параллелизма 100, что достаточно.

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

Трудно найти последовательности без пропусков. Я предлагаю использовать равнину serial столбец вместо. Создать вид с помощью оконной функции row_number() создать последовательность без пропусков:

CREATE VIEW foo AS
SELECT *, row_number() OVER (ORDER BY serial_col) AS gapless_id
FROM   tbl;

Вот идея, которая должна поддерживать как высокую производительность, так и высокий параллелизм:

  1. Используйте очень параллельную, кэшированную последовательность Oracle, чтобы сгенерировать тупой уникальный идентификатор для строки таблицы без пробелов. Вызовите эту сущность MASTER_TABLE

  2. Используйте тупой уникальный идентификатор для всей внутренней ссылочной целостности от MASTER_TABLE до других зависимых подробных таблиц.

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

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

Другие вопросы по тегам