Djangoプログラムでは、データベースが更新されたレコードを取得できません.

2264 ワード

一、問題
以前、djangoアプリケーションに定期的にデータベースからデータを取得する処理のウィジェットを書いてみました.このウィジェットのコードは大体このように見えます.
import os, sys
import time

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")

from apps.my_models import Toy

if __name__ == "__main__":
    while True:
        broken_toys = Toy.objects.filter(is_broken=1)

        ## do someting good to these toys
        print broken_toys
        .....

        ## for some rest ;)
        time.sleep(5)

実行後の検出:データベース
toys
テーブルレコードが変更された場合、プログラムが実行されるたびに取得される
broken_toys
同じです.Strange~
二、検査
最初はQuerySetキャッシュの影響かと思っていましたが、pdbでフォローしてみると関係ないことがわかりました.stackoverflowも探して、似たような問題を発見しました.upvoteの最高の答えはmysqlのテーブルに関連していると述べた.当時はよく見ていなかったが、googleフォーラムのこの投稿から重視された.
簡単に言えばinnodbのデフォルトの場合、各transaction内の読み出しは、初回読み出し時の内容である.上のサンプルプログラムは私が同じ接続を使っていて、しかもすべて読み取り操作なので、この問題が発生しました.
MySQL公式サイトから重要な内容を抜粋し、特に真ん中の部分に注意して印象を深めます.
consistent read A read operation that uses snapshot information to present query results based on a point in time, regardless of changes performed by other transactions running at the same time. If queried data has been changed by another transaction, the original data is reconstructed based on the contents of the undo log. This technique avoids some of the locking issues that can reduce concurrency by forcing transactions to wait for other transactions to finish.
With the repeatable read isolation level, the snapshot is based on the time when the first read operation is performed. With the read committed isolation level, the snapshot is reset to the time of each consistent read operation.
Consistent read is the default mode in which InnoDB processes SELECT statements in READ COMMITTED and REPEATABLE READ isolation levels. Because a consistent read does not set any locks on the tables it accesses, other sessions are free to modify those tables while a consistent read is being performed on the table.
詳細については、公式サイトの説明を参照してください.
  • set-transaction
  • innodb-consistent-read

  • 三、解決方法
    問題点が分かり、解決方法も多い.
  • 調整モード:set transaction isolation level read committed.
  • updateを使用:broken_toys.update()は、transaction
  • を強制的にリフレッシュします.
  • 新しい接続の使用:
  • 参照
    個人的には3つ目の傾向がある.