Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vqFC8-007HKM-0r for pgsql-general@arkaria.postgresql.org; Wed, 11 Feb 2026 18:44:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vqFC7-0056l5-1W for pgsql-general@arkaria.postgresql.org; Wed, 11 Feb 2026 18:44:12 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vqFC7-0056ku-0I for pgsql-general@lists.postgresql.org; Wed, 11 Feb 2026 18:44:11 +0000 Received: from mout02.posteo.de ([185.67.36.66]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vqFC5-00000000C8M-2t0x for pgsql-general@postgresql.org; Wed, 11 Feb 2026 18:44:11 +0000 Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 0BE07240101 for ; Wed, 11 Feb 2026 19:44:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=posteo.de; s=2017; t=1770835448; bh=Sm229aqUPqgTerbnDfxEadJsA2FpS/CvDkdYJjqf0K4=; h=Content-Type:Message-ID:Date:MIME-Version:To:From:Subject:From; b=iy4Ux3Bj0jb6Y0/hCVXAFYQannGbRKASyyEe9ysbz7BApsqdH2zxQcTdpKEc4R4+W Yt99qh+gwvqocLfeu9VtuOaS0qMJ9BcyrybdMylwNHq3bXDRR/YggfbITVTu9c8N1D S8EcXwqbYNyJgMJB+5DGDh8GUInqJb/7wjOgourkvzpRrs3ImR/wqbuq7FtQ6e4ysX ksodOtUGUruKOSmFUcJwjGjQ+H7I9d4tAdTBycYhnyST5kQKGTiVf/ihgxpNRWITOa AmEoLPnpqnBCkMU9xJgsiiJmDxQJJHyz3xyfHaULqV+9M9cyLMslNaLBSTZzrWjrfa n0SmVXMp7uzsg== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4fB6lq2Mdcz9rxB for ; Wed, 11 Feb 2026 19:44:07 +0100 (CET) Content-Type: multipart/alternative; boundary="------------3qaiIn0fkcwb6iTVWjS8hCFK" Message-ID: <93fb937f-9f4d-4bd7-b7e6-51d5f98859d9@posteo.de> Date: Wed, 11 Feb 2026 18:44:07 +0000 MIME-Version: 1.0 Content-Language: en-US To: pgsql-general@postgresql.org From: Nico Heller Subject: Guarantee order of batched pg_advisory_xact_lock List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------3qaiIn0fkcwb6iTVWjS8hCFK Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Good day, I am working on a system which re-centralizes a distributed system to publish the aggregated data somewhere. We make heavy use of advisory locks to prevent race conditions in our application. We use the following bulk query as we sometimes need acquire multiple locks at the same time and want to avoid round-trips to the database: |WITH keys(key) AS (SELECT unnest(:keysToLock)) SELECT pg_advisory_xact_lock(hashtextextended(key, 0)) FROM keys| :keysToLock is a text[] parameter which is pre-sorted in our application. This pre-sorting is done to prevent dead locks when two concurrent transactions try acquire the same advisory locks (e.g. [a,b,c] [b,a,c] can easily deadlock). We thought this would be enough, but we occasionally still run into deadlocks. I tried to research this topic and learned that the SQL standard does not guarantee the order of execution without ORDER BY, so I whipped up the following variant: |SELECT pg_advisory_xact_lock(hashtextextended(ordered_keys.key, 0)) FROM ( SELECT * FROM unnest(?) WITH ORDINALITY keys(key, index) ORDER BY index ) ordered_keys| Would this suffice? It's really difficult for me to find reliable documentation about this topic. A user on StackOverflow suggested this variant to create an "optimization fence" so that the subquery cannot be flattened: |SELECT pg_advisory_xact_lock(hashtextextended(ordered_keys.key, 0)) FROM (SELECT * FROM unnest(?) WITH ORDINALITY AS keys(key, index) ORDER BY index /* a no-op, but it prevents subquery flattening */ OFFSET 0) AS ordered_keys;| Somehow, wanting a guaranteed order of pg_advisory_xact_lock execution turned out to be quite complicated. So what is the correct way to do this? And I would love for some form of documentation link to read up on this. Thank you for your time, Nico Heller --------------3qaiIn0fkcwb6iTVWjS8hCFK Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 7bit

Good day,

I am working on a system which re-centralizes a distributed system to publish the aggregated data somewhere.
We make heavy use of advisory locks to prevent race conditions in our application.

We use the following bulk query as we sometimes need acquire multiple locks at the same time and want to avoid round-trips to the database:

WITH keys(key) AS (SELECT unnest(:keysToLock))
SELECT pg_advisory_xact_lock(hashtextextended(key, 0)) FROM keys

:keysToLock is a text[] parameter which is pre-sorted in our application. This pre-sorting is done to prevent dead locks when two concurrent transactions try acquire the same advisory locks (e.g. [a,b,c] [b,a,c] can easily deadlock).
We thought this would be enough, but we occasionally still run into deadlocks.

I tried to research this topic and learned that the SQL standard does not guarantee the order of execution without ORDER BY, so I whipped up the following variant:

SELECT pg_advisory_xact_lock(hashtextextended(ordered_keys.key, 0))
FROM (
    SELECT * FROM unnest(?) WITH ORDINALITY keys(key, index) ORDER BY index
) ordered_keys

Would this suffice? It's really difficult for me to find reliable documentation about this topic.
A user on StackOverflow suggested this variant to create an "optimization fence" so that the subquery cannot be flattened:

SELECT pg_advisory_xact_lock(hashtextextended(ordered_keys.key, 0))
FROM (SELECT *
      FROM unnest(?) WITH ORDINALITY AS keys(key, index)
      ORDER BY index
      /* a no-op, but it prevents subquery flattening */
      OFFSET 0) AS ordered_keys;

Somehow, wanting a guaranteed order of pg_advisory_xact_lock execution turned out to be quite complicated.

So what is the correct way to do this? And I would love for some form of documentation link to read up on this.

Thank you for your time,
Nico Heller

--------------3qaiIn0fkcwb6iTVWjS8hCFK--