Add optional FOR UPDATE clause to QuerySets

3 views
Skip to first unread message

Sebastian Bauer

unread,
May 16, 2008, 3:56:44 PM5/16/08
to django-d...@googlegroups.com
could someone tell me when this ticket will be add to trunk:

http://code.djangoproject.com/ticket/2705

its very important to me because im writing game and i need this to finish

Thanks for answer

PS. sorry for my really bad english

Russell Keith-Magee

unread,
May 17, 2008, 4:38:05 AM5/17/08
to django-d...@googlegroups.com
On Sat, May 17, 2008 at 3:56 AM, Sebastian Bauer <ad...@ugame.net.pl> wrote:
>
> could someone tell me when this ticket will be add to trunk:
>
> http://code.djangoproject.com/ticket/2705
>
> its very important to me because im writing game and i need this to finish

There is no simple answer to your question. It will be committed when
it is committed. Based on the comments in the ticket, the basic idea
has been accepted, but the implementation still needs some work. The
last time a core developer looked at the ticket, there were still some
issues to resolve. The core developers are focussed on getting v1.0
out the door, so looking at patches for feature additions like this is
not a high priority at present.

However, I would point out that if you are happy with the patch as it
is, there is nothing preventing you from using it. You can apply the
patch to your local version of Django and use it in your game without
any difficulty. If/When the patch is committed to trunk, you can
switch back to using a vanilla trunk checkout, rather than your
locally modified version.

Yours,
Russ Magee %-)

Sebastian Bauer

unread,
May 17, 2008, 7:04:36 AM5/17/08
to django-d...@googlegroups.com
Russell Keith-Magee pisze:
Thank you for answer, but for update, i think, is really important for commercial projects and places where you need to be sure that no one changed row in parallel

Sebastian Noack

unread,
May 23, 2008, 12:53:07 PM5/23/08
to django-d...@googlegroups.com
On Sat, 17 May 2008 13:04:36 +0200
Sebastian Bauer <ad...@ugame.net.pl> wrote:
> Thank you for answer, but for update, i think, is really important
> for commercial projects and places where you need to be sure that no
> one changed row in parallel

I don't think that commercial projects have an exceptional position. But
if FOR UPDATE is important for your project, you can use the patch as
Russel already told you.

But if the only thing you want to do is to ensure that data aren't
changed between several SQL statements you can go with transactions,
which are supported very well, by django at the moment.

Regards
Sebastian Noack

signature.asc

Sebastian Bauer

unread,
May 26, 2008, 3:28:35 AM5/26/08
to django-d...@googlegroups.com
Could you show me how use transactions to do that? because i have very basic knowledge in this area

Sebastian Noack pisze:

Sebastian Noack

unread,
May 26, 2008, 5:38:20 AM5/26/08
to django-d...@googlegroups.com
On Mon, 26 May 2008 09:28:35 +0200
Sebastian Bauer <ad...@ugame.net.pl> wrote:
> Could you show me how use transactions to do that? because i have
> very basic knowledge in this area


from django.db import transaction

@transaction.autocommit
def foo(request):
# Get some data.

# Change some data.

# ...

Now anything you do in foo() is done within a single transaction.

Regards
Sebastian Noack

signature.asc

Collin Grady

unread,
May 26, 2008, 2:04:16 PM5/26/08
to django-d...@googlegroups.com
Sebastian Noack said the following:

> Now anything you do in foo() is done within a single transaction.

Of course, this won't stop another process from querying the same data and then
changing it, resulting in loss of data - hence the need for FOR UDPATE :)

--
Collin Grady

All Finagle Laws may be bypassed by learning the simple art of doing
without thinking.

Sebastian Bauer

unread,
May 26, 2008, 2:20:32 PM5/26/08
to django-d...@googlegroups.com
another way to block other process is lock all table, but this more decrease performance than for update
for example:

tmp = Example.objects.get(pk=1)
tmp.count += 1 # initial count is 0
tmp.save()

some numbers of users execute this part of code in parallel, what will be result? i dont think it will be number of users
in postgresql when you use exclude table locking then other rows cant be get and you get delay
mysql doesnt have exclude locking and only way to exclude lock some data is for update in query

Collin Grady pisze:

Sebastian Noack

unread,
May 26, 2008, 5:46:11 PM5/26/08
to django-d...@googlegroups.com
On Mon, 26 May 2008 11:04:16 -0700
Collin Grady <cgr...@gmail.com> wrote:
> Sebastian Noack said the following:
> > Now anything you do in foo() is done within a single transaction.
>
> Of course, this won't stop another process from querying the same
> data and then changing it, resulting in loss of data - hence the need
> for FOR UDPATE :)

According to
http://www.databasejournal.com/features/mysql/article.php/3382171 this
isn't true. I never proofed it, but as far as I know and written on
this article, one of the concepts of transactions is the isolation of
one transaction from another.


"Isolation: Simply put, data being used for one transaction cannot be
used by another transaction until the first transaction is complete.
Take this example below, where an account balance starts at 900. There
is a single deposit of 100, and a withdrawal of 100, so the balance at
the end should remain the same.

Connection 1: SELECT balance FROM account1;
Connection 2: SELECT balance FROM account1;
Connection 1: UPDATE account1 SET balance = 900+100;
Connection 2: UPDATE account1 SET balance = 900-100;


The balance is now 800, so we have lost 100. These two transactions
should have been isolated, and the result supplied to Connection 2 only
when the transaction from Connection 1 was complete."


Regards
Sebastian Noack

signature.asc

Sebastian Bauer

unread,
May 26, 2008, 6:07:54 PM5/26/08
to django-d...@googlegroups.com
not:

Connection 1: SELECT balance FROM account1;
Connection 2: SELECT balance FROM account1;
Connection 1: UPDATE account1 SET balance = 900+100;
Connection 2: UPDATE account1 SET balance = 900-100;
but:
Connection 1: SELECT balance FROM account1;
Connection 2: SELECT balance FROM account1;
Connection 1: UPDATE account1 SET balance = balance+100;
Connection 2: UPDATE account1 SET balance = balance-100;

small change but big difference
when you use balance=balance+100 syntax calculation is on mysql/postgresql side not django/python/...
and then sql server locking row until commit, but i could be wrong 


Sebastian Noack pisze:

Sebastian Noack

unread,
May 26, 2008, 7:17:35 PM5/26/08
to django-d...@googlegroups.com
On Tue, 27 May 2008 00:07:54 +0200
Sebastian Bauer <ad...@ugame.net.pl> wrote:

> not:
>
> Connection 1: SELECT balance FROM account1;
> Connection 2: SELECT balance FROM account1;
> Connection 1: UPDATE account1 SET balance = 900+100;
> Connection 2: UPDATE account1 SET balance = 900-100;
>
> but:
>
> Connection 1: SELECT balance FROM account1;
> Connection 2: SELECT balance FROM account1;
> Connection 1: UPDATE account1 SET balance = balance+100;
> Connection 2: UPDATE account1 SET balance = balance-100;

I didn't wrote this article, but I assume that the 900 just represents
the result of the previous SELECT.

> when you use balance=balance+100 syntax calculation is on
> mysql/postgresql side not django/python/... and then sql server
> locking row until commit, but i could be wrong

What is the difference? This is why you are using transactions.

BEGIN;
SELECT balance FROM account1; -- Returns only 900.


UPDATE account1 SET balance = 900+100;

COMMIT;

If i understand transactions correct this has the same effect as just,

UPDATE account1 SET balance = balance+100;

Even if it is done by many parallel connections, because of
transactions are managed by the DBMS too and ensure atomicity,
consistency, isolation and durability of each transaction

Regards
Sebastian Noack

signature.asc

Giovanni Dr. Chiozza

unread,
May 27, 2008, 9:07:48 AM5/27/08
to django-d...@googlegroups.com
DO NOT SEND ME ANY MESSAGGE PLEASE !!

----- Original Message -----
From: "Sebastian Noack" <sebasti...@googlemail.com>
To: <django-d...@googlegroups.com>
Sent: Monday, May 26, 2008 11:46 PM
Subject: Re: Add optional FOR UPDATE clause to QuerySets


Giovanni Dr. Chiozza

unread,
May 27, 2008, 9:07:54 AM5/27/08
to django-d...@googlegroups.com



No virus found in this incoming message.
Checked by AVG.
Version: 8.0.100 / Virus Database: 269.24.1/1466 - Release Date: 25/05/2008 18.49

Jean-François

unread,
May 28, 2008, 2:58:37 AM5/28/08
to Django developers


On 27 mai, 01:17, Sebastian Noack <sebastian.no...@googlemail.com>
wrote:

[snip]

> Even if it is done by many parallel connections, because of
> transactions are managed by the DBMS too and ensure atomicity,
> consistency, isolation and durability of each transaction
>
[snip]

The problem is that DBMS don't use the same default isolation level.
Many DBMS use a read committed default, some a repeatable read and
very few a serializable level.
Some DBMS are even unable to support serializable.
The "for update" clause generally implied a repeatable read.

Read committed allow another transaction to update a record previously
read by your transaction.
Repeatable read allow phantom which mean that if you redo a select new
records can appear.

For more information on isoloation level you can read
http://en.wikipedia.org/wiki/Isolation_(computer_science)


JF
Reply all
Reply to author
Forward
0 new messages