Thread: BUG #18882: Unexpected write skew at SERIALIZABLE with psycopg2.connect()
BUG #18882: Unexpected write skew at SERIALIZABLE with psycopg2.connect()
From
PG Bug reporting form
Date:
The following bug has been logged on the website: Bug reference: 18882 Logged by: Huicong Xu Email address: 2023103793@ruc.edu.cn PostgreSQL version: 17.2 Operating system: Ubuntu 22.04 Description: Hello. When I was using Python to connect to the PG database for large-scale testing, I noticed a problem. As the example below demonstrates, this example should report an error at the serializable isolation level because there is a cycle between the two transactions. However, when I executed this script it did not report an error, but when I used SQL it did. What do you think about this matter? Thank you very much for your help. --- Init Database CREATE TABLE tJ6mtoSl (ID INT, VAL INT, c0 REAL UNIQUE PRIMARY KEY NOT NULL, c1 INT NULL , c2 TEXT ); CREATE TABLE tEJybmqs (ID INT, VAL INT, c0 BOOLEAN , c1 BOOLEAN , c2 DECIMAL(50, 28) ); INSERT INTO tJ6mtoSl (ID, VAL, c0, c1, c2) VALUES (14710, 16726, 3795.9601, 9535, '-636554895'); INSERT INTO tJ6mtoSl (ID, VAL, c0, c1, c2) VALUES (14691, 16705, 4091.6018, 1351, ''); INSERT INTO tJ6mtoSl (ID, VAL, c0, c1, c2) VALUES (14711, 16727, 9685.3172, 2824, '<'); INSERT INTO tEJybmqs (ID, VAL, c0, c1, c2) VALUES (14714, 16730, TRUE, FALSE, 4074.8459); INSERT INTO tEJybmqs (ID, VAL, c0, c1, c2) VALUES (14715, 16731, FALSE, FALSE, 7592.0412); ---case conn1 = psycopg2.connect(**dbconfig) conn2 = psycopg2.connect(**dbconfig) cur1 = conn1.cursor() cur2 = conn2.cursor() try: cur1.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;") cur1.execute("START TRANSACTION;") cur2.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;") cur2.execute("START TRANSACTION;") cur1.execute("SELECT * FROM tJ6mtoSl WHERE ( tJ6mtoSl.c1 < 1646 AND tJ6mtoSl.c1 >= 1061 ) AND (tJ6mtoSl.c0 >= 100) ORDER BY tJ6mtoSl.ID;") print(cur1.fetchall()) cur2.execute("SELECT * FROM tEJybmqs WHERE ( tEJybmqs.c1 = FALSE ) ORDER BY tEJybmqs.ID;") print(cur2.fetchall()) cur2.execute("UPDATE tJ6mtoSl SET VAL = 16732 WHERE ( tJ6mtoSl.c1 < 1646 AND tJ6mtoSl.c1 >= 1061 ) AND (tJ6mtoSl.c0 >= 100);") cur2.execute("COMMIT;") cur1.execute("DELETE FROM tEJybmqs WHERE ( tEJybmqs.c1 = FALSE );") cur1.execute("COMMIT;") except Exception as e: print(e) cur1.close() cur2.close() --- I see [(14691, 16705, 4091.6018, 1351, '')] [(14714, 16730, True, False, Decimal('4074.8459000000000000000000000000')), (14715, 16731, False, False, Decimal('7592.0412000000000000000000000000'))]
Re: BUG #18882: Unexpected write skew at SERIALIZABLE with psycopg2.connect()
From
Thomas Munro
Date:
On Tue, Apr 8, 2025 at 9:18 PM PG Bug reporting form <noreply@postgresql.org> wrote: > cur1.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL > SERIALIZABLE;") > cur1.execute("START TRANSACTION;") I think it sends an implicit BEGIN, so you're already in a transaction, and then START TRANSACTION (= BEGIN) is ignored, and SET SESSION will affect the *next* transaction. I bet your log says "WARNING: there is already a transaction in progress". I think there is a psycopg2 way to request SERIALIZABLE, something like conn1.set_isolation_level(extensions.ISOLATION_LEVEL_SERIALIZABLE), or you could probably use SET TRANSACTION ISOLATION LEVEL SERIALIZABLE instead of the SESSION version.