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 表使用的是 MyISAM 引擎而不是 InnoDB 引擎。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 回答