DB API 2.0 and transactions
Christopher J. Bottaro
cjbottaro at alumni.cs.utexas.edu
Fri Jun 10 17:25:20 EDT 2005
<posted & mailed>
Magnus Lycka wrote:
> You might have spotted a fairly nasty bug there!
> PostgreSQL violates the SQL standards by running in autocommit mode
> unless you explicitly perform its non-standard BEGIN command. If you
> are right about the behaviour you describe, the PostgreSQL binding
> for Python that you use may have taken the easy route, and performs
> a "BEGIN" on connect and after every commit or rollback.
Check this out...
<code>
import pgdb
import time
print time.ctime()
db = pgdb.connect(user='test', host='localhost', database='test')
time.sleep(5)
db.cursor().execute('insert into time_test
(datetime)
values
(CURRENT_TIMESTAMP)')
db.commit()
curs = db.cursor()
curs.execute('select datetime from time_test order by datetime desc limit
1')
row = curs.fetchone()
print row[0]
</code>
<output>
Fri Jun 10 17:27:21 2005
'2005-06-10 17:27:21.654897-05'
</output>
Notice the times are exactly the same instead of 5 sec difference.
What do you make of that? Some other replies to this thread seemed to
indicate that this is expected and proper behavior.
-- C
> If so, this is a serious bug, and should be reported as one. The correct
> thing to do is to insert the BEGIN just before the first SQL statement
> that is affecting transactions. Of course, this means that the binding
> needs to keep track of transaction state, and this makes it a little
> bit more complicated. You'd need something like this in the binding:
>
> class connection:
> def __init__(...):
> ...
> self.inTxn = False
>
> def commit(...):
> ...
> self.inTxn = False
>
> def rollback(...):
> ...
> self.inTxn = False
>
> def execute(...):
> ...
> if not self.inTxn:
> perform the BEGIN command against the backend
> self.inTxn = True
> ...
>
> Actually, this isn't perfect either, because not all SQL commands
> (should) initate transactions, but it's a lot closer to what we want.
>
> This bug has implications far beyond timestamps. Imagine two transaction
> running with isolation level set to e.g. serializable. Transaction A
> updates the AMOUNT column in various rows of table X, and transaction
> B calculates the sum of all AMOUNTS.
>
> Lets say they run over time like this, with | marking begin and >
> commit (N.B. ASCII art, you need a fixed font):
>
> ...|--A-->.......|--A-->........
> ...........|-B->.........|-B->..
>
> This works as expected...but imagine transactions implicitly
> begin too early:
>
> |-----A-->|---------A-->|-------
> |------------B->|----------B->|-
>
> This will cause the aggregations in B to show "delayed" results.
> Not at all what one might expect...
>
>
> For more about isolation levels, see e.g. here:
> http://pgsqld.active-venture.com/transaction-iso.html
More information about the Python-list
mailing list