“将来”是否有更好的方法退出MySQL InnoDB日志?


16

我在MySQL 5.0中遇到此InnoDB错误。Mysqld干净地停止了,但是后来我设法丢失了ib_logfile0和ib_logfile1。现在,在干净启动之后,InnoDB已经完成了“崩溃恢复”。我经历了innodb_force_recovery = 4业务,修复了一个挂起的MyISAM表,除此之外,现在可以进行复制了。大数字表示:

111116 15:49:36  InnoDB: Error: page 393457 log sequence number 111 561,760,232
InnoDB: is in the future! Current system log sequence number 70 3,946,969,851.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

这是在从属服务器上。上面的错误产生了数百个。我找到了这个答案:“插入并删除> 64 GB的数据,以便日志序列号膨胀得足够大”。

http://forums.mysql.com/read.php?22,50163,50163#msg-50163

这个64GB的神奇数字来自4GB * 16,那里的那个家伙的innodb日志“主要数字”需要从0增加到15。矿山的数量从70增加到111 = 164 GB。这将需要5天。我将继续加快脚本的速度,并并行运行它以加快脚本的速度。同时,我希望其他人有更好的答案。真傻


一个有希望的答案是:“如果它是从服务器,最好的解决方案实际上是将数据库移到一边,并从主服务器安装新快照。” 不幸的是,全天候24x7生产25个数据库中的20,000个表,混合了MyISAM和InnoDB。在重新启动复制之前,关闭所有路径并进行全新的完全复制将花费很长时间。
IcarusNM

4
现在,我在创建和删除164 gigs数据的无意义竞争中屈指可数。我听到的唯一选择是核对此从站上的所有内容并从头开始。全部有效地在两个文件中更改一个数字。肯定有一些InnoDB工程师提供了专业建议。有没有人在Emacs中打开过ib_logfile0,以十六进制形式找到了幻数,并进行了更改?
IcarusNM

这是一篇很棒的文章,介绍了几种实现方法。Percona绝对是MySQL的权威。 percona.com/blog/2013/09/11/…–
jbrahy

Answers:


10

这是一种非常罕见的情况。我希望再也不用InnoDB结束了,“日志序列号在将来!” 错误。由于我的特定细节,重建/还原服务器数据是不得已的选择。一些帮助作弊的技巧是个好主意,但最终,我决定继续改进我的Perl脚本,以玩这个愚蠢的游戏,并尽我所能地进行每小时最多的演出。哎呀,这是一个很好的系统压力测试。

请记住:目标是增加一个计数器(“日志序列号”),该计数器存储在ib_logfile0ib_logfile1的头中。这是为了伪造InnoDB,因此它将忽略明显的时间扭曲并继续生活。但没人知道如何编辑该号码。或者,如果他们知道,没有人在说话。

这是我的最终产品。YMMV,但是使用mysql的REPEAT函数在内部生成数据非常高效。

 #!/usr/bin/perl
 use DBI;
 $table = shift || die;
 $dbh = DBI->connect("DBI:mysql:junk:host=localhost", "user", "pass"); #Edit "junk" (DB name), user, and pass to suit.
 $dbh->do("DROP TABLE IF EXISTS $table");
 $dbh->do("CREATE TABLE $table (str TEXT) ENGINE=INNODB");
 $sth = $dbh->prepare("INSERT INTO $table (str) VALUES (REPEAT(?,1000000))");
 foreach (1..50) {
    $sth->execute('0123456789');   # 10 MB
 }
 $dbh->do("DELETE FROM $table");

我建议的食谱:

  1. 创建一个“垃圾”数据库
  2. 保存上述perl脚本作为junk.pl
  3. 一次运行junk.pl data1junk.pl data2junk.pl data3等,以与数据库服务器一样多的CPU核心启动。打开多个外壳并将每个运行包装在Bash循环中:while true; do date; junk.pl dataX; done

观察您的LSN增长,也许在另一个循环中:

 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 3871092821
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 4209892586
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 125 85212387

最大的数字是一个无符号的32位INT,它将包装为4GB,每次都增加较小的数字。在上面的例子中,它只是从124滚动到125。您的目标隐藏在mysqld.log中,该地址首先使您谷歌搜索该可笑的解决方案。一旦您越过终点线,就是这样!吹牛角!释放纸屑!

补充工具栏:这发现了mysqld 5.0 w / REPEAT中的一个有趣的错误:如果转到20 MB,它将翻转一些内部计数器并将其滚动到〜96 KB。任何地方都没有警告或错误。我并不想浪费时间进行跟踪。10 MB很棒。如果您确实达到其他限制,则可能会抱怨。我从默认增加了各种innodb缓冲区。调味季节。与往常一样,在一个窗口中观看mysqld.log。



谢谢乔纳斯;那很有意思。我想我可能会坚持上面的方法。他展示了针对正在运行的mysqld使用gdb,我可能永远不会冒险。但是那里也有很好的信息。
IcarusNM 2014年

出于某种奇怪的原因,使用MariaDB时,我没有获得“小数[空格]大数”日志序列号-而是一个“大数”,因此可悲的是,这种方法对我不起作用。好吧,当然,日志会更新,我只是不知道何时停止!
Gwyneth Llewelyn

5

您有三个(3)选项:

选项01:执行主站到从站的rsync(主站的停机)

  • 步骤01:reset master;在主数据库上运行(Zaps Binary Logs)
  • 步骤02:service mysql stop在主控上
  • 步骤03:service mysql stop在奴隶上
  • 步骤04:将rsync / var / lib / mysql从主站传递到从站
  • 步骤05:service mysql start在主控上
  • 步骤06:使用主数据库上的第一个二进制日志作为开始复制的日志。使用该日志的文件大小作为从其开始复制的位置
  • 步骤07:service mysql stop --skip-slave-start在奴隶上
  • 步骤08:运行CHANGE MASTER TO命令以从步骤06确定的日志和位置中设置复制
  • 步骤09:start slave;在从服务器上运行,让复制赶上

选项02:执行主站到从站的rsync(主站的最小停机时间)

  • 步骤01:reset master;在主数据库上运行(Zaps Binary Logs)
  • 步骤02:service mysql stop在奴隶上
  • 步骤03:从主站到从站的rsync / var / lib / mysql
  • 步骤04:重复步骤03,直到两个连续的rsync花费相同的时间
  • 步骤05:service mysql stop在主控上
  • 步骤06:从主站到从站的rsync / var / lib / mysql
  • 步骤07:service mysql start在主控上
  • 步骤08:使用主服务器上的第一个二进制日志作为开始复制的日志。使用该日志的文件大小作为从其开始复制的位置
  • 步骤09:service mysql stop --skip-slave-start在奴隶上
  • 步骤10:运行CHANGE MASTER TO命令以从步骤08确定的日志和位置中设置复制
  • 步骤11:start slave;在从服务器上运行,让复制赶上

选项03:使用XtraBackup

该软件工具不仅会创建正在运行的主服务器的非干扰性副本,还将为您创建相应的ib_logfiles。您将必须设置复制

我已经在此主题上发布到StackExchange

我为雇主的网络托管公司做了很多次这些事情。一位客户有3.7TB的移动空间,大约花费了16个小时。相比之下64GB很小。


在选项02步骤05中,您说要启动主机。它什么时候停止的?实时主服务器上的Rsync很胆小。我印象深刻 幸运的是,我正在使用innodb_file_per_table。但是最终,您必须硬着头皮,将主服务器停止足够长的时间,以便在开始复制之前运行最后一个rsync。我可能会使用这种可能性,但这是一个非常活跃的DBMS。我将在XtraBackup中查看我的信息。
IcarusNM 2011年

@IcarusNM:啊,错字了。我纠正了。谢谢 !!!
RolandoMySQLDBA 2011年

选项02可能仍会使用一些工作。例如,您应该在步骤1之前执行步骤2。您可能希望在其中的某个位置放一个RESET SLAVE。在步骤4中键入。在步骤5中您说“第一个二进制日志”,但实际上是“仅”或“最后一个”二进制日志。并且您应该使用mysqlbinlog确定日志位置,而不是文件大小。除非您在某个时候停止了主机,否则所有这些仍然无法正常工作。将日志位置/时间基于rsync完成的风险最大。
IcarusNM

在过去的4年中,我一直与DB Hosting客户(在TeraByte Range中拥有数据)一起执行OPTION 2。每次在运行中的服务器上运行。您唯一可能犯的错误是在奴隶身上。该错误将在于复制是否正确设置。此外,RESET SLAVE它很有用,尤其是当您堆积了许多GB的中继日志时。在rsync进程和复制重建之后,请记住CHANGE MASTER TO命令也将为您清除中继日志。
RolandoMySQLDBA 2011年

嗯...很奇怪。我使用xtrabackup(一如既往)设置了我的从属服务器,但仍然收到这些日志错误(percona mysql 5.5.x)……似乎在这个从属服务器上出了点问题,我必须再次做一次。
哈拉尔德2012年

2

我发现也许有更酷的方法可以解决分区表上的此问题。我需要删除几年前的分区,并且必须在2014年添加一些分区。几乎所有分区都报告此错误,旧分区也是如此。非常讨厌的崩溃。

因此,当删除旧文件并使用MAXVALUE分区的REORGANIZE(最后一个)时,它将创建可以的新文件,因此我得到的警告越来越少。同时,它有助于增加日志序列计数器,因此我不需要插入虚假数据。我在主服务器上发生这种情况...

所以这:

ALTER TABLE Events DROP PARTITION p1530 , p1535 , p1540 , p1545 , 
p1550, p1555 , p1560 , p1565 , p1570 , p1575 , p1580 , p1585 , p1590 , 
p1595 , p1600 , p1605 , p1610 , p1615 , p1620 , p1625 , p1630 , p1635 , 
p1640 , p1645 , p1650 , p1655 , p1660 , p1665 , p1670 , p1675 , p1680 , 
p1685 , p1690 , p1695 , p1700 , p1705 , p1710 , p1715 , p1720 , p1725 , 
p1730 , p1735 , p1740 , p1745 , p1750 , p1755 , p1760 , p1765 , p1770 , 
p1775 , p1780 , p1785 , p1790 , p1795 , p1800 , p1805 , p1810 , p1815 , 
p1820 , p1825 , p1830 , p1835 , p1840;

还有这个:

ALTER table Events REORGANIZE PARTITION p3000 INTO (
PARTITION p3500 VALUES LESS THAN (TO_DAYS('2013-01-01')),
PARTITION p3510 VALUES LESS THAN (TO_DAYS('2013-01-04')),
PARTITION p3520 VALUES LESS THAN (TO_DAYS('2013-01-07')),
PARTITION p3530 VALUES LESS THAN (TO_DAYS('2013-01-10'))
...
PARTITION p4740 VALUES LESS THAN (TO_DAYS('2014-01-08')),
PARTITION p9000 VALUES LESS THAN MAXVALUE)

这将有效地删除更改中的每个分区,并使用其中的内容的临时副本重新创建该分区。您可以根据需要在每个表中执行此操作,我的应用程序允许执行此操作,因此无需担心同步备份等问题。

现在,对于表的其余部分,由于我没有触摸过该过程中的所有分区,因此某些分区将保留日志顺序警告,对于那些已损坏但被此重组操作覆盖的分区,我可能会运行以下命令:

ALTER TABLE Events REBUILD PARTITION p0, p1;

或者那个

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

因此,这让我开始思考,您可以使用普通的原始表来完成此操作,通过哈希临时添加分区,然后再将其删除(或者保留它们,我强烈建议您使用分区)。

我正在使用mariadb,而不是mysql(所以是XtraDB)

也许这对某人有帮助。到目前为止,我仍在运行它。更改ENGINE似乎也可以完成这项工作,因此我将它在MyIsam和他们之间又回到InnoDB。

这是很合逻辑的,如果您更改ENGINE,该表将从innodb中消失,因此不再是问题。

ALTER TABLE Events ENGINE=MyISAM;
ALTER TABLE Events ENGINE=InnoDB;

它似乎在这里工作。我可以确认分区表上的一些内容:

  • ALTER TABLE xyz ENGINE = InnoDB非常慢,到Aria(mariadb)快一倍,但通常是增加日志序列计数器的慢方法
  • ALTER TABLE xyz REBUILD PARTITION ALL是“修复”表并帮助增加计数器的最快方法
  • ALTER TABLE xyz ANALYZE PARTITION ALL被慢速地修复到前者,并且不重写签出可以的分区。REBUILD确保重写为临时表架构。

我在几张桌子上用了最后一张。当尝试打开文件时会发生警告,并且打开的每个分区定义都有一个警告,但存在计数器问题。今天几乎快要过去了最后几张桌子的柜台。我认为一旦处理完毕,就需要刷新二进制日志。

更新:现在我可以得出一些结论,设法解决了这个问题。

  • 我的崩溃是由于重组Aria格式(MariaDB)的表上的分区而引起的。
  • (对我而言)对分区进行重建的最佳和最快方法是使序列计数器增加。更改引擎的速度很慢,您需要执行两次以影响innodb。与MyIsam或Aria相比,更改为innoDB相当慢。
  • 我升级到了MariaDB 5.3,而不是5.5(was:5.2),它可以正常工作。我认为aria,5.5中的分区(以及已确认的错误)存在太多问题,无法使用该组合。
  • 确实应该有更好的方法来重置日志序列计数器。

在MariaDB下,您可以使用USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(来源:dba.stackexchange.com/questions/35073/…)快速更改所有表,并将其发送到文件中以作为一系列命令来执行。
Gwyneth Llewelyn
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.