3

私の python スクリプトは、行属性を読み取り、インクリメントします。この関数を 4 つの異なるスレッドから呼び出します。

 def update_row():
      row = myTable.select(myTable.q.id==1, forUpdate=True)[0]
      row.count += 1
      print "thread %s updated count to %s" %(threading.currentThread(),row.count)

 th1 = threading.Thread(target=update_row, )
 th2 = threading.Thread(target=update_row, )
 th3 = threading.Thread(target=update_row, )
 th4 = threading.Thread(target=update_row, )
 print "Before starting threads count=",myTable.get(1).count
 th1.start()
 th2.start()
 th3.start()
 th4.start()

いくつかの実行で、カウント値が常に 4 増加するとは限らないことに気付きました。

私の質問:同じオブジェクトスレッドセーフで更新操作を行うための sqlobject (forUpdate 以外の、私には機能しないように見える) のメカニズムはありますか?

シリアル化のために update_row() 関数で threading.Lock() を単純に使用できることはわかっていますが、それは避けたいと思います。

env に関する追加情報: 基礎となるデータベースは MySql、python 2.7、sqlobject ver 1.5 です。

4

1 に答える 1

4

多くのグーグル検索の結果、答えが見つかりました
。基礎となるmysqlテーブルがInnoDBエンジンではなくMyISAMエンジンを使用していたため、以前はうまくいきませんでした。MyISAM は、トランザクションと行レベルのロックをサポートしていません。

def update_row():
      try:
          trans = conn.transaction()
          row = myTable.select(myTable.q.id==1, connection=trans, forUpdate=True)[0]
          print "thread %s select done:"%threading.currentThread(),row.count
          row.count += 1
          print "thread %s updated count:"%threading.currentThread(),row.count
      except Exception, fault:
          print str(fault)
          trans.rollback()
      else:
          trans.commit()
于 2014-03-18T09:45:27.257 に答える