如何在不离线数小时的情况下将 66,862,521 行表从 MyISAM 转换为 InnoDB?

Hen*_*ann 18 mysql innodb

是否有可能(以及如何)将巨大的 MyISAM 表转换为 InnoDB,而无需使应用程序脱机。它需要每秒向该表中插入几行,但可以将其挂起约 2 分钟。

显然 ALTER TABLE ... engine=innodb 将不起作用。因此,我计划使用 innodb 引擎创建一个新表并将内容复制到其中。最后,暂停应用程序日志线程和重命名表。

不幸的是,即使以 100 行的小批量复制在一段时间后也会产生明显的延迟。

编辑:永远不会更改现有行,此表用于记录。

Der*_*ney 15

创建一个 Master-Master 设置,如下所示:

  • 创建第二个 master,MasterB
  • MasterB 作为奴隶 logTable
  • 创建logTable_new为 innodb
  • INSERT INTO logTable_new SELECT * FROM logTable在 MasterB 上运行(伪代码),它将复制发送到 MasterA
  • logTable_newMasterA 完成同步时,换出表


Joe*_*Joe 10

鉴于以下约束:

我不在乎谈话需要几天或几周。但它必须在后台运行,不需要应用程序的停机时间,也不会造成明显的延迟

当您进行日志记录时,如果您有一些设置标记的好方法,以便您可以知道您开始该过程的内容,那么您就可以重新应用任何日志,或者将日志写出到文本文件中你可以稍后摄取它们 LOAD DATA INFILE

部分问题在于,小批量写入意味着必须一遍又一遍地重新计算索引;你最好一次运行它,但这可能会导致系统出现一些“明显”的滞后......但你不必在你的生产服务器上这样做。

  1. 暂停日志记录或设置一些标记,以便您可以在以后重新应用日志。
  2. 将您的 MyISM 表复制到另一个系统
  3. 在另一个系统上,以不同的名称创建一个 InnoDB 表并迁移数据 (转储并使用它甚至可能更快LOAD DATA INFILE
  4. 将 InnoDB 表复制回原系统
  5. 为日志设置另一个标记。
  6. 从最后两个标记之间将所有日志重新应用到新表。
  7. (如果第 6 步超过一分钟左右,重复第 5 步和第 6 步,直到只有几秒钟)
  8. 交换表(将旧表重命名为 table_BACKUP,旧表名称下的新表)
  9. 赶上自上次标记以来的日志。


Dav*_*ett 9

不幸的是,即使以 100 行的小批量复制在一段时间后也会产生明显的延迟。

您是在每个批次之间添加任何延迟,还是只是批量更新并在上一个批次之后直接运行每个批次?

如果是这样,请尝试使用您喜欢的语言编写转换脚本,例如:

repeat
    copy oldest 100 rows that haven't been copied yet to new table
    sleep for as long as that update took
until there are <100 rows unprocessed
stop logging service
move the last few rows
rename tables
restart logging
delete the old table when you are sure the conversion has worked
Run Code Online (Sandbox Code Playgroud)

这应该确保转换不会占用服务器容量的一半以上,即使考虑到系统使用随时间变化而施加的负载差异。

或者,如果您想在服务相对空闲时使用尽可能多的时间,但在数据库需要为其用户做一些工作时退出(可能暂停很长时间),请替换sleep for as long as the update tookif the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>. 这意味着它可以在安静的时候继续前进,但在服务器忙于执行其正常工作负载时会完全暂停。确定负载将取决于您的操作系统 - 在 Linux 下和类似的 1 分钟负载平均值来自/proc/loadavguptime应该做的输出。<lower measure>并且<upper measure>可能是相同的值,尽管在这样的控件中通常会有差异,因此您的过程不会继续启动然后立即暂停,因为它自己的重新启动会对负载测量产生影响。

当然,这不适用于可能修改旧行的表,但对于像您描述的日志表这样的日志表可以正常工作。

在这种情况下,您将要忽略填充新表创建索引的通常智慧。虽然当您希望事情尽可能快时这确实更有效(对系统其余部分的影响该死),但在这种情况下,您不希望在流程结束时出现大量负载,因为索引完全是一次性创建的,因为这是一个在事情变得忙碌时您无法暂停的过程。