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 1voP7u-0033oM-1m for pgsql-general@arkaria.postgresql.org; Fri, 06 Feb 2026 16:56: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 1voP7t-004vbt-2C for pgsql-general@arkaria.postgresql.org; Fri, 06 Feb 2026 16:56:13 +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 1voP7t-004vbl-16 for pgsql-general@lists.postgresql.org; Fri, 06 Feb 2026 16:56:13 +0000 Received: from crumpet.qq2.net ([80.247.17.44]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1voP7q-00000001OTi-0O0U for pgsql-general@lists.postgresql.org; Fri, 06 Feb 2026 16:56:12 +0000 Received: from by crumpet.qq2.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_128_GCM:128) (Exim 4.94.2) (envelope-from ) id 1voP7m-007giO-KH for pgsql-general@lists.postgresql.org ; Fri, 06 Feb 2026 16:56:06 +0000 Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-4362d4050c1so699768f8f.2 for ; Fri, 06 Feb 2026 08:56:06 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCWZx7t0r71RmRZr5WCpe363j8iirWm4OKY9uusc7+iwFptThcsrt4bfbFWvnY+B3kU0ePT774QeevS3lKpI@lists.postgresql.org X-Gm-Message-State: AOJu0YwhcL2BO1VDzSMQPbxKpK9BpjesFaDWAQ9yhtuD+cEf+ipIdI1P Lx9TlVw25kHa20N/s+g6gFqHVB24sqHe/kulMCwq966IobciHYaUFrpzottPvwpC2IlGf1WAy99 ruIAcewGOg2h3CQ4XvoXkar3fSwFEzw== X-Received: by 2002:a05:6000:420e:b0:435:d84f:4853 with SMTP id ffacd0b85a97d-4362938b24dmr4878065f8f.35.1770396965997; Fri, 06 Feb 2026 08:56:05 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Geoff Winkless Date: Fri, 6 Feb 2026 16:55:49 +0000 X-Gmail-Original-Message-ID: X-Gm-Features: AZwV_Qgz3cem8RZcMlYfmmHYFl2Z66ZQd-NdP2ni995EI6Yr0JF4qqY6_5kiNhs Message-ID: To: Adrian Klaver , "pgsql-generallists.postgresql.org" Content-Type: text/plain; charset="UTF-8" X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on crumpet.qq2.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 Subject: Re: UNLOGGED table CREATEd on one connection not immediately visible to another connection X-SA-Exim-Version: 4.2.1 (built Sat, 13 Feb 2021 17:57:42 +0000) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, 29 Jan 2026 at 15:09, Adrian Klaver wrote: > Question, why is this not run in a single process? A little to do with logic separation but honestly mainly because of history. Also the need for the first process to be allowed to get on with other stuff while the work is done by the second process. Yes, it could be threaded, but this is 35-year-old code, and while we could rewrite it to use threads but that really shouldn't be required, should it? > Provide the code for the procedure(s) that create the table and send the > ID to the other process. I can't provide the entire code, because it's not open. It's using libpq and our own wrapper around PQsendQuery that handles things like autoretries, auto-reconnection and grabbing all results to ensure the connection is kept in a consistent state. What we do INSERT INTO sometable (somefield) VALUES ('string') RETURNING seqid We use that seqid to create a uniquely-named temp table CREATE UNLOGGED TABLE qtemp%d (scid INTEGER PRIMARY KEY DEFAULT 0 NOT NULL) We then do (in a loop around a list) INSERT INTO qtemp%d (scid) values (%d) ON CONFLICT DO NOTHING with the seqid from the first query and the values from our list Each of these queries is tested for success by our wrapper. We would see a failure in the log if any part of this had failed. None of these queries is inside an explicit transaction. We then send that seqid value to the second process's socket, and that process then runs a query that looks something like: SELECT DISTINCT 0 AS gid, lid FROM galloc INNER JOIN qtemp%d as qt USING(sc_id) WHERE EXISTS (SELECT 1 FROM stg where s_id in (993,996,994,995,997) and stg.party=0 AND stg.scid=qt.scid) AND NOT EXISTS (SELECT 1 FROM gl WHERE gl.lid=galloc.lid AND gl.g_id=422)' We get the return error: Primary: relation "qtempXXX" does not exist (where XXX is the seqid) The logging is verbose enough that I can see the seqid being used to CREATE and INSERT the values matches the value that is being received by the second process (and the query that is run matches that value). Further, as I said previously it's very important that the receiving process sometimes succeeds on retry - our wrapper retries the same query string five times on fatal error, just in case of transient failures. Sometimes we get 5 fatal errors in the log, sometimes only 2 (after which it then continues successfully). Were it not for the retries succeeding I could accept that we might somehow have failed to create the table (even though we are testing for the success of the CREATE and the INSERTs), but it seems bizarre to me that this could fail and then fail and then suddenly work. There is no way the code could be dropping the table and then recreating it after transmitting the seqid: there is no facility in the code to drop the table. We do have a cron job that drops all qtemp* tables overnight (at 23:00), but this error is occurring at times nowhere near that (e.g. yesterday we saw this error at 13:28). I'm fully prepared to accept that I'm doing something wrong because I've tried to reproduce the error using a couple of test PHP processes with a socket between them and haven't managed to reproduce the failure in several million tries, but I'm at a loss as to what to look for, so any suggestion would be gratefully accepted. Geoff