-
-
Notifications
You must be signed in to change notification settings - Fork 516
Description
Originally submitted by: MordicusEtCubitus
Hi,
I've upgraded psycopg to 2.4.5 and associated ZPsycoPGDA on my website and transactions appear to be reseted each time a new ZSQL method is called in same request. Using postgresql 9.1.6.
My understanding of the error is based, in parts, on the following articles:
[1] http://psycopg.lighthouseapp.com/projects/62710/tickets/125-pool-broken-for-zope
[2] http://grokbase.com/t/postgresql/psycopg/11893j8ns1/zpsycopgda-isolation-levels-bug
Description of the issue:
I am executing two queries in same HTTP request, ie two ZSQL methods
Query one:
insert into shop_user_order ( ) values
( )
SELECT currval( 'shop_user_order_id_order_seq' ) AS id_order
This one executes an insert and return the new id_order of this insert
Query two:
insert into shop_user_order_item ( , reference, title, price, price_promo, tva, count, present, code_promo )
values
(
)
Then I've got the error:
insert or update on table "shop_user_order_item" violates foreign key constraint "shop_user_order_item_fkey" DETAIL: Key (id_order)=(9886) is not present in table "shop_user_order".
First, I've thought that each query was executed in a separated thread/connection, so the new serial of the order was not found in second query.
While reading the article in [2] I've found that some isolation levels where missing and existing one having wrong values.
But proposed patch was in [2] was not solving the issue.
Thus, adding a commit statement just after insert in first query or using auto-commit/read uncommited isolation state were solving the issue.
Clearly, queries were not executed in the same transaction.
While reading [1] I've undersood that second query was calling
self.getcursor()
itself calling self.getconn()
itself doing and init (def getconn(self, init=True):) and reseting connection.
So, updating in db.py
def getcursor(self):
conn = self.getconn()
return conn.cursor()
To
def getcursor(self):
conn = self.getconn(False)
return conn.cursor()
was solving the issue.
The "open" method is already doing self.getconn(True) so previous change is not risky.
About isolation level values, I've also noticed an error:
PostgresSQL sources in file access/xact.h defines below values:
define XACT_READ_UNCOMMITTED 0
define XACT_READ_COMMITTED 1
define XACT_REPEATABLE_READ 2
define XACT_SERIALIZABLE 3
And in psycopg, file extensions.py we have:
"""Isolation level values."""
ISOLATION_LEVEL_AUTOCOMMIT = 0
ISOLATION_LEVEL_READ_UNCOMMITTED = 4
ISOLATION_LEVEL_READ_COMMITTED = 1
ISOLATION_LEVEL_REPEATABLE_READ = 2
ISOLATION_LEVEL_SERIALIZABLE = 3
So it appears we have a confusion between auto-commit and READ_UNCOMMITTED
I hope this can help.
By the way, if you need testors for next release of ZPsycoPGDA, I'll be glad to help to.
With kind regards.