Консультативные блокировки PostgreSQL не работают в транзакциях?

Я использую C# с драйвером Npgsql для подключения к postgresql 9.6.9. У меня есть два сервера, которые подключаются к одной базе данных, выполняя следующий код инициализации в цикле, чтобы убедиться, что они конфликтуют друг с другом:

using (var txScope = new TransactionScope())
using (var connection = Connection())
{
    connection.EnlistTransaction(Transaction.Current);
    using (var cmd = new NpgsqlCommand("SELECT pg_advisory_lock(1024)", connection))
    using (cmd.ExecuteReader()) { }

    // The following line fails:
    using (var cmd = new NpgsqlCommand(@"CREATE OR REPLACE FUNCTION update_column()   
        RETURNS TRIGGER AS $$ BEGIN RETURN NEW; END; $$ language 'plpgsql'; ", connection))
    {
        cmd.ExecuteNonQuery();
    }

    using (var cmd = new NpgsqlCommand("SELECT pg_advisory_unlock(1024)", connection))
    using (cmd.ExecuteReader()) { }

    txScope.Complete();
}

Консультативная блокировка должна предотвращать выполнение запроса CREATE более одного раза в настоящее время, но он постоянно дает сбой с «Npgsql.PostgresException (0x80004005): XX000: кортеж одновременно обновляется», где создается функция. Если я использую LOCK TABLE вместо рекомендательной блокировки, это сработает. Если я делаю это без транзакций, тоже работает. Однако это кажется хрупким дизайном, чтобы удалять транзакции каждый раз, когда я хочу заблокировать.

Примечание. Я пробовал это с API транзакций Npgsql и с BEGIN / COMMIT с тем же результатом.

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

BEGIN ... COMMIT полностью поддерживает «параллелизм» - в противном случае никакие транзакции не работали бы в Postgres.
a_horse_with_no_name 19.09.2018 10:50

@a_horse_with_no_name Во втором предложении этих документов говорится, что он не поддерживается. Автор имел в виду описать только свою библиотеку, а не весь PostgreSQL ?: npgsql.org/doc/transactions.html

piojo 19.09.2018 10:53

Ну верно предложение «не поддерживает вложенные транзакции». Но «не поддерживает одновременные транзакции» верно только в отношении одновременных транзакций, запущенных в сеансе тем же (= соединение). Несколько сеансов (= соединения) могут абсолютно использовать одновременные транзакции с использованием BEGIN ... COMMIT.

a_horse_with_no_name 19.09.2018 10:55

@a_horse_with_no_name Знаете ли вы, поддерживается ли begin / commit / begin / commit в рамках одного соединения? Поскольку соединения объединены в пул, это будет необходимая функция. (У меня были проблемы с BeginTransaction(), но я не помню тестовый пример.)

piojo 19.09.2018 10:58

Я не знаю C# или Npgsql, но Postgres может с этим справиться (он работает без проблем через JDBC)

a_horse_with_no_name 19.09.2018 11:00

@a_horse_with_no_name Спасибо за информацию. Метод BeginTransaction определенно не работал с пулом соединений, но я еще не пробовал BEGIN / COMMIT.

piojo 19.09.2018 11:07

Я никогда не использовал npgsql или ado.net. Если бы пришлось, я бы решил эту проблему, установив log_statement=all на сервере, а затем заглянув в файл журнала сервера, чтобы увидеть, что на самом деле было отправлено.

jjanes 19.09.2018 15:11

Первый и последний cmd.ExecuteNonQuery (), возможно, не подходят, поскольку содержимое cmd определенно является запросами.

jjanes 19.09.2018 15:14

@jjanes Спасибо. Замена их на using (cmd.ExecuteReader()) сработала, но не решила проблему.

piojo 20.09.2018 05:08

@a_horse_with_no_name Ради правильности: pg_advisory_lock () создает блокировку уровня сеанса, на которую транзакции никак не влияют. Блокировку уровня транзакции можно получить с помощью pg_advisory_xact_lock ().

Ivan Shagin 06.03.2019 10:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
840
0

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