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

CREATE SCHEMA IF NOT EXISTS предизвиква грешка при дублиране на ключ

Това е малко брадавица в изпълнението на IF NOT EXISTS за таблици и схеми. По принцип те са опит за изместване и PostgreSQL не се справя чисто с условията на състезание. Безопасно е, но е грозно.

Ако схемата се създава едновременно в друга сесия, но все още не е ангажирана, тогава тя едновременно съществува и не съществува, в зависимост от това кой сте и как изглеждате. Не е възможно други транзакции да "видят" новата схема в системните каталози, защото тя не е ангажирана, така че е запис в pg_namespace не се вижда от други транзакции. Така че CREATE SCHEMA / CREATE TABLE се опитва да го създаде, защото, що се отнася до него, обектът не съществува.

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

За правилно коригиране на това PostgreSQL вероятно ще се нуждае от заключване на предикат, където може да заключи потенциала за ред . Това може да бъде добавено като част от текущата работа за прилагане на UPSERT .

За тези конкретни команди PostgreSQL вероятно би могъл да извърши мръсно четене на системните каталози, където може да види незавършени промени. След това може да изчака необвързаната транзакция да се ангажира или върне назад, да направи отново мръсното четене, за да види дали някой друг чака, и да опита отново. Но това би имало състояние на състезание, при което някой друг може да създаде схемата между момента, в който извършвате четене, за да проверите за нея, и когато се опитвате да я създадете.

Така че IF NOT EXISTS вариантите ще трябва да:

  • Проверете дали схемата съществува; ако стане, завършете, без да правите нищо.
  • Опит за създаване на таблицата
  • Ако създаването е неуспешно поради уникална грешка в ограничението, опитайте отново от началото
  • Ако създаването на таблица е успешно, завършете

Доколкото знам, никой не го е приложил или са опитали и не е прието. При този подход биха възникнали възможни проблеми със скоростта на изгаряне на идентификатора на транзакция и т.н.

Мисля, че това е някакъв вид грешка, но това е грешка от типа „да, знаем“, а не от типа „ще се заемем да поправим това“. Чувствайте се свободни да публикувате в pgsql-bugs за това; най-малкото в документацията трябва да се споменава това предупреждение относно IF NOT EXISTS .

Не препоръчвам да правите DDL едновременно по този начин.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как мога да променя регистъра на буквите за всяка буква в низ с SQL?

  2. Как да получа списък с имена на последователности в Postgres?

  3. Postgresql :Връзката е отказана. Проверете дали името на хоста и порта са правилни и че администраторът на пощата приема TCP/IP връзки

  4. Вземете n групирани категории и сумирайте останалите в една

  5. Свързване на pgadmin към postgres в докер