不能在mariadb中以原子方式执行select + update事务

时间:2016-04-10 23:22:58

标签: mysql python-3.4 mariadb peewee

我试图通过使用"任务"来尝试并行化python脚本。 mariadb中的表,其中每行描述一个任务,我的脚本的每个运行实例都执行类似这样的简化python + peewee代码:

with db.transaction() as txn: 
   result = list(Table.raw("select id from tasks where started=0 limit 1"))
   if len(result) == 0:
      sys.exit("nothing left to do")

   my_next_task = result[0]

   # mark this task as started
   Table.raw("update tasks set started=1 where id=%s" % my_next_task.id)

# process my_next_task

但是,当我同时启动我的脚本的两个实例时,它们都开始处理相同的任务。在这种情况下,我是否误解了交易应该如何运作?

1 个答案:

答案 0 :(得分:1)

试试这个。保证以下代码在执行任务之前只有1个线程获取锁

1.您正在进行交易的事实,确保一次只有一个线程可以进行更新

2.注意,我们需要检查start = 0.这样可以确保只有1个线程可以进行更新

with db.transaction() as txn: 
   result = list(Table.raw("select id from tasks where started=0 limit 1"))

   // The update query should return number of rows updated. So if a thread updates the task, it should return 1, which means it acquired a lock. If not, it means the thread didn't acquire the lock
   got_lock = Table.raw("update tasks set started=1 where id=%s and started = 0" % my_next_task.id) > 0 

   if len(result) == 0:
      sys.exit("nothing left to do")

   my_next_task = if(got_lock) result[0] else return