Оператор lock table device in exclusive mode
принимает очень ограничительную блокировку таблицы ( «эксклюзивный режим» ).Изменение таблицы с внешним ключом для родительской таблицы требует довольно безобидной блокировки общего ресурса для родительской таблицы (например, вы не можете обрезать таблицу, когда строки, ссылающиеся на нее, потенциально обновляются).
На самом деле, пробуя это сейчас, я не могу воспроизвести ваше поведение блокировки (на 8.4.4, как вы).Я сделал:
create table device(device_id serial primary key, value text not null);
create table device_foo(device_foo_id serial primary key, device_id int not null references device(device_id) on delete cascade, value text not null);
insert into device(value) values('FOO'),('BAR'),('QUUX');
insert into device_foo(device_id, value) select device_id, v.value from (values('mumble'),('grumble'),('fumble')) v(value), device;
И затем в двух одновременных соединениях я сделал:
<1>=# begin; lock table device in exclusive mode;
<2>=# begin; update device_foo set value = value || 'x';
Мне кажется, это эквивалентно тому, что вы делаете, но я не понимаюблокировка второго сеанса - он немедленно выдает «ОБНОВЛЕНИЕ 9», как и ожидалось. Вставка в блоки device_foo
, как и следовало ожидать, как и оператор обновления, устанавливающий столбец device_id
.Я могу видеть ExclusiveLock в pg_locks
из сеанса db1 в сеансе db2.Это также блокирует, если я делаю «выбрать * с устройства для обмена», что является утверждением, которое вы видите в ошибке взаимоблокировки.Я также не получаю взаимоблокировку, если я делаю "select * from device_foo для обновления" из соединения db1, в то время как db2 блокируется, пытаясь обновить столбец device_id в device_foo.
Обновление строки действительно помечает строкукак заблокировано, но эта блокировка не видна в pg_locks.Также требуется блокировка таблицы, чтобы заблокировать любого, кто пытается удалить / усечь / переиндексировать таблицу во время обновления одной из ее строк.
Чтобы заблокировать таблицу device
от одновременных обновлений, вы можетехотите менее строгий режим блокировки.В руководстве предлагается "поделиться строкой эксклюзивно" для этого вида деятельности.Хотя это только на один уровень ниже «эксклюзивного», оно совместимо с утверждением «выберите ... для обмена».
Так что, на самом деле, открытый вопрос - что выдает этот «выбор ...»для обмена "запрос?: -S Это похоже на утверждение, предназначенное для утверждения целостности внешнего ключа, но я не могу воспроизвести его.