Reader

请教一个关于并发控制的问题

| V2EX - 技术 | Default

现在有这样一个函数 processBatch ,负责读取数据,执行一些操作后再更新它们,相关的数据库操作都在事务内执行。伪代码如下:

function processBatch():
    tx = db.beginTransaction()
    // 1. 批量读取:取出最多 N 条“待处理”数据
    items = tx.query("SELECT * FROM tasks WHERE status = 'PENDING' LIMIT N")
    
    for item in items:
        // 2. 业务处理
        doBusinessLogic(item)
        // 3. 更新状态
        tx.execute("UPDATE tasks SET status = 'DONE' WHERE id = ?", item.id)
    tx.commit()
// 线程 A
spawn threadA:
    processBatch()

// 线程 B (几乎同时执行)
spawn threadB:
    processBatch()

但由于 processBatch 在多个地方都会被调用,因此存在并发问题。线程 A 和线程 B 执行时可能查询到同一批数据,导致这批数据被处理两次。解决这个问题有两个方案:

  • 方案 A:在 processBatch 的逻辑中增加锁,这样在任意时刻,该函数都不会并发执行
  • 方案 B:调整数据库事务的隔离级别或锁表,即使 processBatch 并发执行了,底层的数据操作不会出现并发的情况

我的问题是:

  1. 哪个方案更符合最佳实践?原因是什么
  2. 在保持 processBatch 会被多个地方调用不变的前提下,有没有更好的方案?
  3. 如果想学习这类并发相关的问题和解决方案,应该搜索什么关键词

感谢各位赐教