私はpostgres 9.1で作業しており、単純な更新メソッドを過剰に実行するとデッドロック例外が発生します。単純な更新クエリのpostgresのデッドロック
ログによれば、同時に2つの同一の更新が実行されるため、デッドロックが発生します。
更新が設定public.vm_action_info last_on_demand_task_id = $ 1、バージョン=バージョン+ 2回の同一の単純な更新が互いをデッドロックすることができますどのように1
?
私は、ログ
2013-08-18 11:00:24 IDT HINT: See server log for query details.
2013-08-18 11:00:24 IDT STATEMENT: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
2013-08-18 11:00:25 IDT ERROR: deadlock detected
2013-08-18 11:00:25 IDT DETAIL: Process 31533 waits for ShareLock on transaction 4228275; blocked by process 31530.
Process 31530 waits for ExclusiveLock on tuple (0,68) of relation 70337 of database 69205; blocked by process 31533.
Process 31533: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
Process 31530: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
2013-08-18 11:00:25 IDT HINT: See server log for query details.
2013-08-18 11:00:25 IDT STATEMENT: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
2013-08-18 11:00:25 IDT ERROR: deadlock detected
2013-08-18 11:00:25 IDT DETAIL: Process 31530 waits for ExclusiveLock on tuple (0,68) of relation 70337 of database 69205; blocked by process 31876.
Process 31876 waits for ShareLock on transaction 4228275; blocked by process 31530.
Process 31530: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
Process 31876: update public.vm_action_info set last_on_demand_task_id=$1, version=version+1 where id=$2
のスキーマを取得していますエラーは次のとおりです。
CREATE TABLE vm_action_info(
id integer NOT NULL,
version integer NOT NULL DEFAULT 0,
vm_info_id integer NOT NULL,
last_exit_code integer,
bundle_action_id integer NOT NULL,
last_result_change_time numeric NOT NULL,
last_completed_vm_task_id integer,
last_on_demand_task_id bigint,
CONSTRAINT vm_action_info_pkey PRIMARY KEY (id),
CONSTRAINT vm_action_info_bundle_action_id_fk FOREIGN KEY (bundle_action_id)
REFERENCES bundle_action (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT vm_discovery_info_fk FOREIGN KEY (vm_info_id)
REFERENCES vm_info (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
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 DELETE NO ACTION,
CONSTRAINT vm_task_last_task_fk FOREIGN KEY (last_completed_vm_task_id)
REFERENCES vm_task (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (OIDS=FALSE);
ALTER TABLE vm_action_info
OWNER TO vadm;
-- Index: vm_action_info_vm_info_id_index
-- DROP INDEX vm_action_info_vm_info_id_index;
CREATE INDEX vm_action_info_vm_info_id_index
ON vm_action_info
USING btree (vm_info_id);
CREATE TABLE vm_task
(
id integer NOT NULL,
version integer NOT NULL DEFAULT 0,
vm_action_info_id integer NOT NULL,
creation_time numeric NOT NULL DEFAULT 0,
task_state text NOT NULL,
triggered_by text NOT NULL,
bundle_param_revision bigint NOT NULL DEFAULT 0,
execution_time bigint,
expiration_time bigint,
username text,
completion_time bigint,
completion_status text,
completion_error text,
CONSTRAINT vm_task_pkey PRIMARY KEY (id),
CONSTRAINT vm_action_info_fk FOREIGN KEY (vm_action_info_id)
REFERENCES vm_action_info (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
ALTER TABLE vm_task
OWNER TO vadm;
-- Index: vm_task_creation_time_index
-- DROP INDEX vm_task_creation_time_index ;
CREATE INDEX vm_task_creation_time_index
ON vm_task
USING btree
(creation_time);
彼らはそれほど単純ではありません。フィールドにはFKのconstantがあります(インデックスを更新する必要があります)。遅延可能なフィーリングが最初に延期されましたか? (相違が生じないとは思わない) – wildplasser
FK制約を変更したくないのは、私がgenralのシステムにどのような影響を与えるのか完全にはわからないからです。一度に1つのクエリしか実行できないという制限をコードに追加することで、この問題は解決されますが、クエリがどのようにしてデッドロックを引き起こすかを理解できません。すべてのロックは同じ順序で取得されるので、実際には起こらないはずです。ポストグルが実際には存在しないデッドロックを誤って検出する可能性はありますか? – moshe
あなたは 'すべてのロックが同じ順序で取得されました 'と書いていますが、単純な更新だけではなく、この単一の更新よりも多くのロックコマンドで構成されています。はいの場合は、コード全体を表示してください。 – krokodilko