今天的话很难,我正在努力把它写清楚,以便我可以帮助你帮助我。下面存在一些矫枉过正,ymmv。
我正在将大约 48m 记录从 table1 迁移到 table2,都是 InnoDB。我能够通过 user_id 识别要从 table1 中剔除的记录(“user_id=3 输入的任何记录都移出 table1 并进入 table2”)。我在单实例设置中获得了工作代码的第一次通过,我需要扩展它以便能够通过 AMQP 服务器运行迁移过程,以便我可以通过多个消费者运行作业(即我正在运行消费者/jobs 在同一作业的 2 个实例中并行运行)在循环设置中,其中消费者都同时运行。我希望能够扩大到 10 个消费者来快速完成这项工作,否则单个实例大约需要 15 天才能完成这项工作。
该代码每次运行都会选择与查询条件匹配的最旧的 2000 条记录。问题是,如果我有 2 个代码实例正在运行并选择记录,那么 instance1 将获取 id 的 1-2000,而在几乎完全相同的时间启动的 instance2 也将获取 1-2000,因为 instance1 没有完成将 0-2000 移出 table1 并且这些 id 仍将存在于 table1 中。
好的,没问题。我添加了一个控制表来记录要排除的记录——它允许 instance1 说“我有记录 1-2000”,这样当 instance2 启动并去查询时,它会说“我应该排除什么 id?” 基于查询控制表作为其“给我接下来的 2000 条记录”的一部分,以便 instance2 将获取 id 的 2001 到 4001,然后更新控制表以让它知道 instance2 的 id 为 2001 到 4001。所以如果有instance3 然后它会知道在启动请求下一个 2k 记录时忽略 id 的 1 到 4001。
当一个实例将一个条目写入锁定的控制表时,它会将其写入为“[first_id_found] 和 [last_id_found]”,或“5671 和 7671”。我使用 ' 和 ' 因为文本进入 sql BETWEEN 子句。
从 table1 中选择 id,其中 id 不在 1565 和 1567 之间,id 不在 1568 和 1570 之间,created_by=3 order by id asc limit 0, 2000
问题:
我需要锁定的唯一表是控制表,以便我确信一旦实例有权访问控制表,它将能够找到要省略的记录以及编写自己的省略记录,以便释放锁后访问表的下一个实例control
将在其中找到最新数据。
但是我需要将锁留在原处,直到查询table1
完成,并且我可以确定结果集中的第一个和最后一个 id,以便我可以将它们添加到control
表中,以便下一个启动的实例知道要排除什么。
请注意,控制文件既不是table1
也不是table2
,并且我没有指定table1
或table2
因为我不需要锁定其中任何一个,我也不想要一个,因为其他进程正在访问表并且我不想阻止从其他正在运行的进程访问table1
或table2
。
所以伪代码如下所示:
// lock control table
// find all control table records (multiple workers = possible multiple records) indicating which id ranges to omit
// build "table1.id not between x and y" strings for each control record found
// query table1 with "not between" into array via PDO::fetchAll() to get the ids of N records that no other instance is working with <<-- the problem
// find first and last ids in result set
// add control table record to `params` field with value = "[first_id_found] and [last_id_found]"
// unlock control table
// process array
当我查询 table1 时,我没有返回任何记录。不正确,我有 4800 万条记录。检查 errorInfo() 向我显示错误情况:
“表 'table1' 未使用 LOCK TABLES 锁定”
我不想 lock table1
,但它看起来像因为它在 LOCK TABLES 被放置control
在一个 UNLOCK TABLES 之前和之前被查询,我处于某种事务模式,所有要使用的表都必须有分配的锁定级别。WTF,我在文档中对此一无所知。
table1
当它不在锁定范围内时,为什么我会遇到这个问题?我并不赞同这种策略,它只是我想到的,如果有一种不同的模式会产生与我游戏相同的功能。解决方法?建议?