Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1Yo0FU-0003j8-V1 for pgsql-hackers@arkaria.postgresql.org; Fri, 01 May 2015 02:00:17 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1Yo0FT-0003vC-H9 for pgsql-hackers@arkaria.postgresql.org; Fri, 01 May 2015 02:00:15 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1Yo0FS-0003u9-Ke for pgsql-hackers@postgresql.org; Fri, 01 May 2015 02:00:14 +0000 Received: from mail-pd0-x235.google.com ([2607:f8b0:400e:c02::235]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84) (envelope-from ) id 1Yo0FP-0005CD-Ne for pgsql-hackers@postgresql.org; Fri, 01 May 2015 02:00:13 +0000 Received: by pdbqa5 with SMTP id qa5so78535003pdb.1 for ; Thu, 30 Apr 2015 19:00:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:message-id:date:from:reply-to:user-agent:mime-version:to:cc :subject:references:in-reply-to:content-type :content-transfer-encoding; bh=Fsm4XU3FPATt0DMoAOJjzbuHx1Ja7GV9hUNnZd9oEQQ=; b=OKu6ld4r+bx4MHpi0pZjKvBIGScTtDRfx4AAvHX3xq2Fet/07K0YzTzxf46Uqf8Ygw mphmJyUkebnJkkp0C4GxVnwF17uqITZmlaNEZ/BXXZf93IarXJfb8WE1Aff6OUptGBVQ bqMfKw01xCdtI4zlwnbLoaW0dcx6RXHBHA30FQV2gQJbuiq1PhKukITQ1isbvgNw6nEl njymWB6vHsJ8FYlXsHbVUccS/sL3hvmWZwrPwl41YgM08FhGNoXPg4nP7Z78UjxAP9dy xKQgE60pZhEnMaDaTb8oAefoSMMUNas16d0+i/TB3qToJqPQiPULfdgynxA9qsU9cVyb j4nw== X-Received: by 10.70.24.130 with SMTP id u2mr13539364pdf.147.1430445610829; Thu, 30 Apr 2015 19:00:10 -0700 (PDT) Received: from [172.20.101.172] ([66.201.48.54]) by mx.google.com with ESMTPSA id nl16sm3368254pdb.56.2015.04.30.19.00.07 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 Apr 2015 19:00:09 -0700 (PDT) Message-ID: <5542DE23.6060800@iki.fi> Date: Thu, 30 Apr 2015 19:00:03 -0700 From: Heikki Linnakangas Reply-To: hlinnaka@iki.fi User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.6.0 MIME-Version: 1.0 To: Peter Geoghegan CC: Andres Freund , Jeff Janes , Stephen Frost , Dean Rasheed , Bruce Momjian , Pg Hackers Subject: Re: INSERT ... ON CONFLICT UPDATE/IGNORE 4.0 References: <553EFF0D.4040903@iki.fi> In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -0.8 (/) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org On 04/27/2015 11:02 PM, Peter Geoghegan wrote: > On Mon, Apr 27, 2015 at 8:31 PM, Heikki Linnakangas wrote: >> I thought we had an ironclad scheme to prevent deadlocks like this, so I'd >> like to understand why that happens. > > > Okay. I think I know how it happens (I was always skeptical of the > idea that this would be 100% reliable), but I'll be able to show you > exactly how tomorrow. I'll have pg_xlogdump output then. I was able to reproduce this, using two sessions, so that on session does a regular INSERT, and another does INSERT ON CONFLICT, after adding a sleep(5) to a strategic place. So this was indeed a live bug, reproducible even without the hack you had to allow ON CONFLICT UPDATE with exclusion constraints. Fortunately this is easy to fix. Here's how to reproduce: 1. Insert "sleep(5)" into ExecInsertIndexTuples, just after the index_insert() call. 2. Create the test table and index: create extension btree_gist; create table foo (id int4, constraint foo_x exclude using gist (id with =) ); 3. Launch two psql sessions, A and B. Do the following: A: set deadlock_timeout='10s'; B: set deadlock_timeout='20s'; A: begin; select txid_current(); B: begin; select txid_current(); A: insert into foo values (1) on conflict do nothing; (the insert will hit the sleep(5) - quickly perform the second insert quickly: ) B: insert into foo values (1); At this point, both transactions have already inserted the tuple to the heap. A has done so speculatively, but B has done a regular insert. B will find A's tuple and wait until A's speculative insertion completes. A will find B's tuple, and wait until B completes, and you get the deadlock. Thanks to the way the deadlock_timeout's are set, A will detect the deadlock first and abort. That's not cool with ON CONFLICT IGNORE. To fix that, we need to fix the "livelock insurance" check so that A does not wait for B here. Because B is not a speculative insertion, A should cancel its speculative insertion and retry instead. (I pushed the one-line fix for that to your github repository) - Heikki -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers