Received: from maia.hub.org (maia-5.hub.org [200.46.204.29]) by mail.postgresql.org (Postfix) with ESMTP id 95FFDB5DBFB for ; Wed, 28 Sep 2011 23:46:39 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.29]) (amavisd-maia, port 10024) with ESMTP id 89304-05 for ; Thu, 29 Sep 2011 02:46:29 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0-rc2 Received: from mail-gy0-f174.google.com (mail-gy0-f174.google.com [209.85.160.174]) by mail.postgresql.org (Postfix) with ESMTP id EB482B5DBE0 for ; Wed, 28 Sep 2011 23:46:28 -0300 (ADT) Received: by gyg10 with SMTP id 10so135378gyg.19 for ; Wed, 28 Sep 2011 19:46:29 -0700 (PDT) Received: by 10.236.129.162 with SMTP id h22mr60525773yhi.44.1317264003980; Wed, 28 Sep 2011 19:40:03 -0700 (PDT) Received: from ayaki.localdomain ([119.11.8.145]) by mx.google.com with ESMTPS id x65sm304694yhg.18.2011.09.28.19.39.59 (version=SSLv3 cipher=OTHER); Wed, 28 Sep 2011 19:40:03 -0700 (PDT) Message-ID: <4E83DA7B.7000101@ringerc.id.au> Date: Thu, 29 Sep 2011 10:39:55 +0800 From: Craig Ringer User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:6.0.2) Gecko/20110906 Thunderbird/6.0.2 MIME-Version: 1.0 To: Maria.L.Wilson-1@nasa.gov CC: "pgsql-admin@postgresql.org" Subject: Re: constraint triggers References: <4E83190B.3070604@nasa.gov> In-Reply-To: <4E83190B.3070604@nasa.gov> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.9 tagged_above=-10 required=5 tests=BAYES_00=-1.9 X-Spam-Level: X-Archive-Number: 201109/211 X-Sequence-Number: 38448 On 09/28/2011 08:54 PM, Maria L. Wilson wrote: > UPDATE dataset > SET gracount = gracount + 1 > WHERE dataset.inv_id = NEW.inv_id; That'll serialize all transactions that touch the same inv_id, so only one may run at once. The second and subsequent ones will block waiting for an update lock on the `dataset' tuple for `inv_id'. When you think about it that's necessary to prevent a wrong result when transaction A then B run this statement, transaction B commits, and transaction A rolls back. What's the correct answer? To fix this you'll need to change how you maintain your `dataset' table. Exactly how depends on your requirements. You can trade read performance off against write performance by INSERTing new rows instead of UPDATEing them, so you do a: SELECT count(inv_id) FROM dataset WHERE dataset.inv_id = ? instead of a SELECT gracount FROM dataset WHERE dataset.inv_id = ? to retrieve your count. You can have both fast reads and fast writes if you accept potentially out-of-date `gracount' data, maintaining `gracount' as a materialized view that you refresh using LISTEN/NOTIFY *after* a transaction commits. It's possible for it to be a little out of date, but writers no longer interfere with each other and readers no longer have to re-do the counting/aggregation work. You can live with serializing writes like you currently do in exchange for the greater read performance of maintaining counts. This may not be so bad once you understand what's happening and can keep transactions that trigger this problem short, preventing them from blocking others while they do unrelated work. In the end, this looks like a simple problem but it isn't when you consider the possibility of transactions rolling back. > Our first try to solve this problem has been to convert these triggers > into a constraint trigger which allows for DEFERRABLE INITIALLY DEFERRED > flags. This, we are finding, is forcing the trigger function to run > after the triggering transaction is completed. We believe this will fix > our locking problem and hopefully speed up our inserts again. That should help, but it's a form of trading timeliness off against performance. Queries within the same transaction won't see the updated `dataset' values, so if you're relying on them for correct operation later in the transaction you could have issues. -- Craig Ringer