Я использую 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
с тем же результатом.
Я думаю, что блокировка правильно работает как мьютекс, так что же не так с транзакцией?