Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nX71p-0007Bi-PW for pgsql-novice@arkaria.postgresql.org; Wed, 23 Mar 2022 19:52:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nX71o-0007uM-MJ for pgsql-novice@arkaria.postgresql.org; Wed, 23 Mar 2022 19:52:20 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nX71o-0007pR-Av for pgsql-novice@lists.postgresql.org; Wed, 23 Mar 2022 19:52:20 +0000 Received: from mail-yb1-xb2d.google.com ([2607:f8b0:4864:20::b2d]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nX71l-00051S-NU for pgsql-novice@lists.postgresql.org; Wed, 23 Mar 2022 19:52:19 +0000 Received: by mail-yb1-xb2d.google.com with SMTP id f38so4696957ybi.3 for ; Wed, 23 Mar 2022 12:52:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:from:date:message-id:subject:to; bh=wb00oeFaXyam82ckjCAELncPYUyKe/jwiqRrPo7SlKk=; b=mYRddNuSu1yrwdfpJOqjYTqGa+DUv+aVuGGu/z5VRS/340Ow4elNx5Lbcy4jEuRKNv z1Jwv4zA/08U6SRzXQiZOHohVYEgVNUPIx4hOuqFZsZNb5I+rrrwFldE6sTnrhK3wzBC pSkhnHXfhj6OMbPve/fPrFG0tUCFF28DIG6bJXn+iJsINsJcQdGZCISUyuevZ/rWHAvi rhmTTGjFjM/Rc5r8J7x6ZGm/zsf3QO7AUcjeO7StpNGgGHCiFGT7d0XEnMEW4u1bw6mP uD6NSSsPdaVnzCAoBdCQ3OWocJp+OTG1gCPwAkW0yuAWH8/k1cZcZq09955Xi6Gnu9aG sjbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=wb00oeFaXyam82ckjCAELncPYUyKe/jwiqRrPo7SlKk=; b=tWD1LXm7DbaUa8H40p134uTzoNec4XT1wBNiZLS4m2w4gmtup1a1iwozD6aW8lFdXN S3/h2KfVAdy7BlU/JR/Lt2MgYWmSSrdB9xgKL/0SAD+Oc+DneJjbvtoNZwbo/0MD2iEw 7wxXXwVo8rbOREX91HvWlUyl+GFZi9DxvuxGeDYNtjHaPSZNdgFlTCU/DR5DGETkuS1+ 2mzw3WvvpFwRmZBDsbj4Tr41KXg9KIyY1sogajFTBt3gjtNqTOQ2imEvoOD7euZRkQIE mDb4EBjORR+nHHyx9vPSd2uHCTuF+PVG+1Wb5yULM53X6d7dnItmQNZJKeAUfTGwcLdN B1Ig== X-Gm-Message-State: AOAM532J02+RLBXB368BSvCeEZRBuy+3vUrxQUkGBl/8WJm2nTvZe54m xY1eLrF85dfogqKNDggWQBq9DVrwYpUQYxuW6OSqM5I4rUDNfA== X-Google-Smtp-Source: ABdhPJyi83MIbyQhWk3h8YpRCVy3C7fjMEfoNa1TJ8EVoPICSV5nRxwrF39V4zhBSN2jc6Wahnx+88i3ImXdpW+ct5U= X-Received: by 2002:a25:ed0e:0:b0:633:8eba:b89f with SMTP id k14-20020a25ed0e000000b006338ebab89fmr1687403ybh.90.1648065136850; Wed, 23 Mar 2022 12:52:16 -0700 (PDT) MIME-Version: 1.0 From: Joe Date: Wed, 23 Mar 2022 12:52:05 -0700 Message-ID: Subject: SELECT FOR UPDATE on rows that don't exist To: pgsql-novice@lists.postgresql.org Content-Type: multipart/alternative; boundary="0000000000000c7a4205dae81169" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000000c7a4205dae81169 Content-Type: text/plain; charset="UTF-8" Hi, I'd like to implement a distributed mutex, and was thinking of this: CREATE TABLE locks (section VARCHAR PRIMARY KEY, holder VARCHAR); And then do: BEGIN; SELECT * FROM locks WHERE section = $1 FOR UPDATE; INSERT INTO locks (section, holder) VALUES ($1, $2); # *1 ... critical section ... DELETE FROM locks WHERE section = $1 and holder = $2; #*2 COMMIT; A few questions: 1) What are the semantics of SELECT FOR UPDATE when the row doesn't exist yet? Without #*1, a simple experiment shows that two processes can be in the critical section at the same time. Add #*1 seems to achieve the desired behavior, but is it really? I didn't find much on the web (it looks like MySQL locks the index meaning the INSERT wouldn't be necessary). If Postgresql was also locking the index, the INSERT would not add anything, but the experiment without the INSERT would have worked. If it's the row being locked, since the row doesn't exist outside the transaction, the second process shouldn't be able to see it and wouldn't block waiting for the first transaction. 2) The DELETE @ #2 is so that the row is never present when not executing in the critical section mainly so that #1 can be a simple insert rather than an upsert. Is there a more standard pattern for this? 3) Using the DB as a distributed mutex seems like a common application but nothing came up in various DB and PostgreSQL books I consulted or on the web. Is this a bad idea, or are there gotchas I'm missing? Thanks! Joe --0000000000000c7a4205dae81169 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,
I'd like to implement a distributed= mutex, and was thinking of this:
CREATE TABLE locks (section VARCHAR PR= IMARY KEY, holder VARCHAR);

And then do:
BEGIN;
SELECT * FROM = locks WHERE section =3D $1 FOR UPDATE;
INSERT INTO locks (section, holde= r) VALUES ($1, $2); =C2=A0# *1

... critical sectio= n ...

DELETE FROM locks WHERE section =3D $1 and h= older =3D $2; #*2
COMMIT;
=C2=A0
A few qu= estions:
1) What are the semantics of SELECT FOR UPDATE when the = row doesn't exist yet?

Without #*1, a simple e= xperiment shows that two processes can be in the critical section at the sa= me time. Add #*1 seems to achieve the desired behavior, but is it really? I= didn't find much on the web (it looks like MySQL locks the index meani= ng the INSERT wouldn't be necessary). If Postgresql was also locking th= e index, the INSERT would not add anything, but the experiment without the = INSERT would have worked. If it's the row being locked, since the row d= oesn't exist outside the transaction, the second process shouldn't = be able to see it and wouldn't block waiting for the first transaction.=

2) The DELETE @ #2 is so that the row is never pr= esent when not executing in the critical section mainly so that #1 can be a= simple insert rather than an upsert. Is there a more standard pattern for = this?

3)=C2=A0 Using the DB as a distributed mutex= seems like a common application but nothing came up in various DB and Post= greSQL books I consulted or on the web. Is this a bad idea, or are there go= tchas I'm missing?

Thanks!
Joe
<= /div>
--0000000000000c7a4205dae81169--