PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

postgresql генерира последователност без празнина

Последователностите не генерират набори от числа без празнини и наистина няма начин да ги накарате да го направят, защото връщане назад или грешка ще „използват“ поредния номер.

Преди време написах статия за това. Той е насочен към Oracle, но всъщност се отнася до основните принципи на числата без празнини и мисля, че същото важи и тук.

Е, пак се случи. Някой е попитал как да се приложи изискване за генериране на серия от числа без празнини и рояк противници се спуснаха към тях, за да кажат (и тук аз леко перифразирам), че това ще убие производителността на системата, това рядко е валидно изискване , че този, който е написал изискването, е идиот, бла-бла-бла.

Както посочих в темата, понякога е истинско законово изискване да се генерират серии от числа без празнини. Номерата на фактури за 2 000 000+ организации в Обединеното кралство, които са регистрирани по ДДС (данък върху продажбите), имат такова изискване и причината за това е доста очевидна:че затруднява скриването на генерирането на приходи от данъчните власти. Виждал съм коментари, че това е изискване в Испания и Португалия и не бих се учудил, ако не е изискване в много други страни.

И така, ако приемем, че това е валидно изискване, при какви обстоятелства серия от числа без празнини* е проблем? Груповото мислене често ви кара да вярвате, че винаги е така, но всъщност това е само потенциален проблем при много специфични обстоятелства.

  1. Поредицата от числа не трябва да има пропуски.
  2. Множество процеса създават обектите, с които е свързан номерът (напр. фактури).
  3. Числата трябва да бъдат генерирани в момента, в който обектът е създаден.

Ако всички тези изисквания трябва да бъдат изпълнени, тогава имате точка на сериализиране във вашето приложение и ще обсъдим това след малко.

Първо нека поговорим за методите за прилагане на изискване за серия от числа, ако можете да откажете някое от тези изисквания.

Ако вашата серия от числа може да има пропуски (и имате множество процеси, изискващи незабавно генериране на числото), тогава използвайте обект Oracle Sequence. Те са с много висока производителност и ситуациите, в които могат да се очакват пропуски, са много добре обсъдени. Не е твърде предизвикателство да се сведе до минимум количеството пропуснати числа, като се полагат усилия за проектиране, за да се сведе до минимум вероятността от неуспех на процеса между генерирането на номера и извършването на транзакцията, ако това е важно.

Ако нямате множество процеси, създаващи обектите (и имате нужда от поредица от числа без празнини, които трябва да бъдат генерирани незабавно), какъвто може да е случаят с пакетното генериране на фактури, тогава вече имате точка на сериализация. Това само по себе си може да не е проблем и може да е ефективен начин за извършване на необходимата операция. Генерирането на числа без празнини е доста тривиално в този случай. Можете да прочетете текущата максимална стойност и да приложите нарастваща стойност към всеки обект с редица техники. Например, ако вмъквате нова партида фактури във вашата таблица с фактури от временна работна таблица, можете:

insert into
  invoices
    (
    invoice#,
    ...)
with curr as (
  select Coalesce(Max(invoice#)) max_invoice#
  from   invoices)
select
  curr.max_invoice#+rownum,
  ...
from
  tmp_invoice
  ...

Разбира се, вие бихте защитили вашия процес, така че само един екземпляр да може да се изпълнява в даден момент (вероятно с DBMS_Lock, ако използвате Oracle), и ще защитите фактурата# с уникален ключ и вероятно ще проверите за липсващи стойности с отделен код, ако наистина ти пука.

Ако не се нуждаете от незабавно генериране на числата (но имате нужда от тях без празнини и множество процеси генерират обектите), тогава можете да позволите на обектите да бъдат генерирани и транзакцията да бъде ангажирана и след това да оставите генерирането на номера на една партида работа. Актуализация на таблицата с обекти или вмъкване в отделна таблица.

И така, ако имаме нужда от трифекта на незабавно генериране на поредица от числа без празнини от множество процеси? Всичко, което можем да направим, е да се опитаме да сведем до минимум периода на сериализиране в процеса и аз предлагам следните съвети и приветствам всякакви допълнителни съвети (или контра съвети, разбира се).

  1. Съхранете текущите си стойности в специална таблица. НЕ използвайте последователност.
  2. Уверете се, че всички процеси използват един и същ код за генериране на нови числа, като го капсулирате във функция или процедура.
  3. Сериализирайте достъпа до генератора на числа с DBMS_Lock, като се уверите, че всяка серия има собствено специално заключване.
  4. Задръжте заключването в генератора на сериите, докато транзакцията за създаване на обект завърши, като освободите заключването при записване
  5. Отложете генерирането на номера до последния възможен момент.
  6. Помислете за въздействието на неочаквана грешка след генериране на числото и преди завършването на комита — приложението ще се върне ли грациозно назад и ще освободи заключването или ще задържи заключването на генератора на сериите, докато сесията се прекъсне по-късно? Какъвто и метод да се използва, ако транзакцията е неуспешна, тогава серийните номера трябва да бъдат „върнати в групата“.
  7. Можете ли да капсулирате цялото нещо в тригер в таблицата на обекта? Можете ли да го капсулирате в таблица или друго извикване на API, което вмъква реда и записва вмъкването автоматично?

Оригинална статия



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как pg_sleep() работи в PostgreSQL

  2. postgresql генерира последователност без празнина

  3. Как да импортирате CSV файл в PostgreSQL

  4. PostgreSQL:използване на изчислена колона в същата заявка

  5. Регистриране на одит за PostgreSQL