Django 1.4で追加されたselect_for_update


Django 1.4からdjangoのQuerySetでselect_for_updateが使えるようになりましたので、簡単に試してみました。


動かしているのは昨日select_relatedの動きを見るのに作ったサンプルアプリです。
sqliteでは試せないのでMySQLを使うようにsettings.pyを変更しました。


python manage.py shell

>>> book = Book.objects.select_for_update().get(pk=1)
>>> 


sqlのログを見てみるとこんなSQLが発行されていて、確かにFOR UPDATEがついています

SELECT `books_book`.`id`, `books_book`.`author_id`, `books_book`.`title` FROM `books_book` WHERE `books_book`.`id` = 1  FOR UPDATE


別のshellをたちあげて同じコードを叩いてみると、ロックの開放待ちになりました

>>> book = Book.objects.select_for_update().get(pk=1)


1つめのshellでbook.save()などすると、ロックが開放されて値が返ってきます。


ロック状態でしばらくほっとくと以下のようなエラーになります

DatabaseError: (1205, 'Lock wait timeout exceeded; try restarting transaction')


ソース見るとnowaitの指定ができそうだったのですが、mysqlだとサポートしてないんですね
こんなエラーになりました

DatabaseError: NOWAIT is not supported on this database backend.


参考)
https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-for-update