从MyISAM在线转换为InnoDB后缺少行


16

我们有一个相当小的数据库,我们希望将其从MyISAM转换为InnoDB。作为数据库新手,我们甚至在不关闭站点的情况下进行了转换(使用alter table)。

现在,转换已完成,似乎缺少许多间歇行。这可能是由于转换期间的操作造成的吗?还是这个问题在其他地方?


哪些表缺少行?您转换的表格或其他表格?
longneck

Answers:


20

执行ALTER更改存储引擎不会使行消失。但是,由于您说您是问题中的“数据库菜鸟”,因此让我提供一些建议。

在修改现有架构或执行任何可能影响数据的操作时,以下是一些基本建议:

  1. 首先进行备份。
  2. 有一个变更计划。
  3. 在离线主机上测试您的计划。
  4. 有一个测试计划来比较数据前后。
  5. 安排并停工。
  6. 停机生效后,请立即进行备份和快照,并确认流量已停止。
  7. 如果您正在运行MYISAM,请在更改之前使用“ CHECK TABLE”来评估要处理的内容。
  8. 以防万一,除了备份外,还应在本地复制表。
  9. 请谨慎操作,启用“ --show warnings”和其他输出,以便您进行更改时具有完整的外观。
  10. 如果数据对您很重要,即使只是在迁移过程中进行咨询,也请聘请一名DBA,以便您有经验丰富的资深人士在您身边。

我可能会遇到更多的问题,但是当出现问题时,以上内容将为您提供选择。

至于丢失的数据/行,没有办法知道w / oa的“之前/之后”快照进行比较。您可以将其与最新备份进行比较,以至少验证一下。


我读了 好的灾难恢复计划。除了前进的计划之外,您的答案比我对我的问题更敏感,因此得到+1。
RolandoMySQLDBA 2011年

1
@randy因为您的回答好,将其标记为最喜欢的问题
techExplorer 2012年

8

在不造成大量停机的情况下将MyISAM转换为InnoDB的最佳方法之一只有一个先决条件:使用复制从站。

这是该计划的鸟瞰图

  1. 创建复制主/从设置
  2. 将奴隶上的每个MyISAM表转换为InnoDB
  3. 将您的应用指向从站

听起来很简单?这背后有很多细节。

创建复制主/从设置

有一种巧妙的方法可以创建从属设备,而不会干扰主设备。我写了两篇文章:

除了阅读有关如何使用rsync的详细信息外,请阅读这两篇文章。

将奴隶上的每个MyISAM表转换为InnoDB

在数据库从站上,可以执行以下SQL语句:

对于MySQL 5.5:

SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM' AND table_schema NOT IN
('information_schema','mysql','performance_schema');

MySQL 5.5之前的MySQL版本

SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM' AND table_schema NOT IN
('information_schema','mysql');

使用查询的输出,您可以为从站创建一个转换脚本。

您必须将这两行放在脚本的顶部:

SET SQL_LOG_BIN = 0;
STOP SLAVE;

该脚本将首先禁用二进制日志记录(如果您配置了从属服务器具有二进制日志),停止复制并将每个MyISAM表转换为InnoDB。

这是创建和执行脚本的方法:

SQLSTMT="SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') FROM information_schema.tables WHERE engine = 'MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema')"
INNODB_CONV_SCRIPT=MassConvertMyISAMTablesToInnoDB.sql
echo "SET SQL_LOG_BIN = 0;" > ${INNODB_CONV_SCRIPT}
echo "STOP SLAVE;" >> ${INNODB_CONV_SCRIPT}
mysql -h(IP of Master) -u... -p... --skip-column-names -A -e"${SQL}" >> ${INNODB_CONV_SCRIPT}
echo "START SLAVE;" >> ${INNODB_CONV_SCRIPT}
mysql -h(IP of Slave) -u... -p... --skip-column-names -A < ${INNODB_CONV_SCRIPT}

将您的应用指向从站

从从机执行SELECT查询。如果您对从站上的数据内容感到满意,请按照以下步骤将您的应用程序指向从站:

  1. 在从站上,运行SHOW SLAVE STATUS\G并确保Seconds_Behind_Master为0
  2. 在从站上,mysqldump -h(从站IP)-u ... -p ...大约现在)
  3. 在主服务器上运行service mysql stop(停机开始)
  4. 重复步骤1
  5. 将您的应用程序指向从站(停机时间在应用程序的第一个连接上结束)

如果您毫发无损地做到这一点,恭喜!!!

附加奖金:如果您设置主/从复制(又名循环复制)而不是从/从,则可以执行以下操作:

  1. 在从站上,运行SHOW SLAVE STATUS\G并确保Seconds_Behind_Master为0
  2. 在从站上,mysqldump -h(从站IP)-u ... -p ...大约现在)
  3. 将您的应用程序指向从站(停机时间在应用程序的第一个连接上开始和结束)
  4. 在新的Master上运行 STOP SLAVE;
  5. 在新的Master上运行 CHANGE MASTER TO MASTER_HOST='';

您现在拥有的是相反的Master / Slave。新的主服务器具有InnoDB数据,而旧的主服务器现在具有MyISAM数据的从服务器。如果拆分读取和写入,则可以从从设备读取数据(从MyISAM读取的数据比InnoDB的读取速度快),写入到主数据库的记录(对InnoDB的事务支持)。就像汉娜·蒙塔纳(Hannah Montana)唱歌一样,两全其美(是的,我有两个女儿喜欢表演)

另一个附加奖励:因为Master现在是InnoDB,所以您可以从Master进行mysqldump,而无需停机,也不会干扰事务。唯一的缺点是增加CPU和磁盘I / O。因此,您可以仅在主服务器(InnoDB)上创建表结构的mysqldump,而仅在从属服务器上创建数据的mysqldump(这样的转储将没有对InnoDB或MyISAM的引用。它只是数据)加上mysqldump的从站具有MyISAM布局的表结构。

由于这种新设置,因此可能会继续下去...

更新2011-08-27 19:50 EDT

我很抱歉。我没有完全阅读问题。您已经进行了交谈

仅当您已经打开了二进制日志记录,并且事先进行了备份时,您才可以

  • 将/ var / lib / mysql还原到另一个位置,例如/ var / lib / mysql2
  • service mysql stop
  • service mysql start --datadir=/var/lib/mysql2
  • mysql将数据库从备份中转储到/root/olddata.sql
  • 从上次备份到/root/changes.sql之后的时间点开始,对/ var / lib / mysql(不是/ var / lib / mysql2)中的所有二进制日志运行mysqlbinlog
  • 将changes.sql加载到mysql中(因为它仍然指向/ var / lib / mysql2)

这应该捕获所有记录的内容,并且应该开始进行转换。同样,这一切都取决于您在上次备份之前已经打开了二进制日志记录。否则,我表示慰问。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.