无法使 mariadb 中的 select+update 事务自动执行
can't make select+update transaction in mariadb execute atomically
我正在尝试通过在 mariadb 中使用 "tasks" table 来并行化 python 脚本,其中每一行描述一个任务,我的脚本的每个 运行 实例做类似这样的简化 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
但是,当我同时启动我的脚本的 2 个实例时,它们都开始处理同一个任务。我是不是误解了交易在这种情况下应该如何运作?
试试这个。以下代码保证只有1个线程在执行任务前获取锁
1.The 事实上你正在做一个事务,确保一次只有 1 个线程可以做更新
2.Note 我们需要检查 started = 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
我正在尝试通过在 mariadb 中使用 "tasks" table 来并行化 python 脚本,其中每一行描述一个任务,我的脚本的每个 运行 实例做类似这样的简化 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
但是,当我同时启动我的脚本的 2 个实例时,它们都开始处理同一个任务。我是不是误解了交易在这种情况下应该如何运作?
试试这个。以下代码保证只有1个线程在执行任务前获取锁
1.The 事实上你正在做一个事务,确保一次只有 1 个线程可以做更新
2.Note 我们需要检查 started = 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