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