Предполагам, че източникът на проблема е кръгова препратка към външен ключ във вашите таблици.
ТАБЛИЦА vm_action_info
==> ВЪНШЕН КЛЮЧ (last_completed_vm_task_id) РЕФЕРЕНЦИИ vm_task (id)
ТАБЛИЦА vm_task
==> ВЪНШЕН КЛЮЧ (vm_action_info_id) РЕФЕРЕНЦИИ vm_action_info (id)
Транзакцията се състои от две стъпки:
Когато две транзакции ще актуализират един и същи запис в vm_action_info
маса в същото време, това ще завърши с блокиране.
Вижте прост тестов случай:
CREATE TABLE vm_task( id integer NOT NULL, version integer NOT NULL DEFAULT 0, vm_action_info_id integer NOT NULL, CONSTRAINT vm_task_pkey PRIMARY KEY (id )) WITH ( OIDS=FALSE ); вмъкване в стойности на vm_task ( 0, 0, 0 ), ( 1, 1, 1 ), ( 2, 2, 2 ); CREATE TABLE vm_action_info( id integer NOT NULL, version integer NOT NULL DEFAULT 0, last_on_demand_task_id bigint, CONSTRAINT vm_action_info_pkey PRIMARY KEY (id ))WITH (OIDS=FALSE);вмъкване в стойности на vm_action_info (0, 0, 0), (1, 1, 1), (2, 2, 2);промяна на таблица vm_taskadd ОГРАНИЧЕНИЕ vm_action_info_fk FOREIGN KEY (vm_action_info_id) REFERENCES vm_action_info (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE;Alter table vm_action_info add CONSTRAINT vm_task_last_on_demand_task_fk FOREIGN KEY (last_on_demand_task_id) REFERENCES vm_task (id) MATCH SIMPLE ON UPDATE NO ACTION ON D; ELETE
В сесия 1 добавяме запис към vm_task, който препраща към id=2 във vm_action_infosession1=> begin;BEGINsession1=> вмъкване в стойности на vm_task( 100, 0, 2 );INSERT 0 1session1=>
По същото време в сесия 2 започва друга транзакция:
session2=> begin;BEGINsession2=> вмъкване в стойности на vm_task( 200, 0, 2 );INSERT 0 1session2=>
След това първата транзакция извършва актуализацията:
session1=> актуализиране на vm_action_info set last_on_demand_task_id=100, version=version+1session1=> където id=2;
но тази команда увисва и чака заключване.....
тогава втората сесия изпълнява актуализацията ........session2=> update vm_action_info set last_on_demand_task_id=200, version=version+1 where id=2;BŁĄD:wykryto zakleszczenieSZCZEGÓŁY:Процес 9384 оценява ExclusiveLock на кротка (0,5) relacji 33083 bazy danych 16393; блокиран обект 3808. Процесът 3808 се оценява на ShareLock при транзакция 976; zablokowany przez 9384.PODPOWIEDŹ:Przejrzyj dziennik servera by znaleźć szczegóły zapytania.session2=>
Открита е безизходица !!!
<предварителен
Това е така, защото и двата INSERT във vm_task поставят споделена ключалка на ред id=2 в таблицата vm_action_info поради препратката към външния ключ. Тогава първата актуализация се опитва да постави заключване за запис на този ред и увисва, защото редът е заключен от друга (втора) транзакция. След това втората актуализация се опитва да заключи същия запис в режим на запис, но той е заключен в споделен режим от първата транзакция. И това води до блокиране.
Мисля, че това може да се избегне, ако поставите заключване на запис на запис във vm_action_info, цялата транзакция трябва да се състои от 5 стъпки:начало; изберете * от vm_action_info, където id=2 за актуализация; вмъкване във vm_task стойности (100, 0, 2); актуализация vm_action_info set last_on_demand_task_id=100, версия=версия+1 където id=2; ангажиране;