从主数据库的原始备份恢复从属 MySQL 数据库时出现 InnoDB 表空间错误

从主数据库的原始备份恢复从属 MySQL 数据库时出现 InnoDB 表空间错误

我有一个主/从复制设置,其中我在超过 7000 个数据库中使用 InnoDB 和 MyISAM 表,我想将这些表从主数据库复制到从数据库以恢复复制。

两台服务器都运行 Ubuntu 10.04.2 LTS(使用 mysql-server 5.1.41-3ubuntu12 包)。最近我尝试升级 MySQL,希望我遇到的某些错误在新版本中已经解决 - 因此我的从属服务器现在是 Ubuntu 10.10。但是,问题似乎是一样的。

我不想破坏我的主服务器,所以我尝试对整个磁盘进行 LVM 快照,以便我可以通过 rsync 将我的数据和日志目录复制到我的从服务器:
/var/lib/mysql:我的 ibdata1 和 ib_logfile0 以及我的所有 .ibd 和 .frm 文件都存储在这里。我使用了 innodb_file_per_table,因此有很多 .idb 文件。/var/log/mysql
:我保存所有二进制日志的地方

复制后,我重置了权限:

chown mysql.mysql /var/lib/mysql -R  
chown mysql.mysql /var/log/mysql -R

我从 /var/lib/mysql 目录中删除了 master.info 和 reply-log.info 文件。(因为对于某些表来说,我的主服务器实际上是另一个主服务器的从属服务器)。

然后我尝试在从服务器上启动 mysql。很快,我开始在 /var/log/mysql.err 中看到大量错误,如下所示:

InnoDB:错误:数据字典中的表空间 ID 为 150238  
InnoDB:但是在文件 ./1_107789/email.ibd 中它是 150747!

或者:

InnoDB:错误:尝试添加名称为“./23_4377/link.ibd”的表空间 148302
InnoDB:将表空间缓存到内存中,但表空间
InnoDB:表空间中已存在名称为“./1_68522/open.ibd”的 148302
InnoDB:内存缓存!

然后时不时地:

110207 13:55:45 InnoDB:文件 ../../../storage/innobase/fil/fil0fil.c 第 603 行中线程 2979265392 中的断言失败
InnoDB:断言失败:0
InnoDB:我们故意产生一个内存陷阱。
InnoDB:向 http://bugs.mysql.com 提交详细的错误报告。
InnoDB:如果你反复遇到断言失败或崩溃,即使
InnoDB:mysqld 启动后,可能会出现
InnoDB:InnoDB 表空间损坏。请参阅
InnoDB:http://dev.mysql.com/doc/refman/5.1/en/forcing-recovery.html
InnoDB:关于强制恢复。
110207 13:55:45 — mysqld 收到信号 6;
这可能是因为你遇到了 bug。这个二进制文件也可能
或者它所链接的某个库已损坏或构建不正确,
或配置错误。此错误也可能由硬件故障引起。
我们将尽力收集一些有助于诊断的信息
问题,但既然我们已经崩溃了,肯定出了问题
这可能会失败。

密钥缓冲区大小=16777216
读取缓冲区大小=131072
最大使用连接数=1
最大线程数=10000
线程连接=1
mysqld 可能会使用最多
key_buffer_size + (read_buffer_size + sort_buffer_size) *max_threads = 868418 K
内存字节数
希望没问题;如果不行,请减少等式中的一些变量。

thd:0xbc5a7138
尝试回溯。您可以使用以下信息来查找
mysqld 死机了。如果此后没有看到任何消息,则表示发生了一些问题
大错特错……
堆栈底部 = 0xb193f13c 线程堆栈 0x30000
/usr/sbin/mysqld(my_print_stacktrace+0x2d) [0xb7638c4d]
/usr/sbin/mysqld(handle_segfault+0x494)[0xb7304854]
[0xb707f400]
/lib/tls/i686/cmov/libc.so.6(中止+0x182) [0xb6d89a82]
/usr/sbin/mysqld(+0x477790) [0xb7514790]
/usr/sbin/mysqld(+0x47795e) [0xb751495e]
/usr/sbin/mysqld(fil_space_get_size+0xdc) [0xb751966c]
/usr/sbin/mysqld(buf_read_page+0xad) [0xb75015dd]
/usr/sbin/mysqld(buf_page_get_gen+0x331) [0xb74fab21]
/usr/sbin/mysqld(btr_get_size+0x190) [0xb75b02b0]
/usr/sbin/mysqld(dict_update_statistics_low+0x50)[0xb7503e70]
/usr/sbin/mysqld(dict_table_get+0xec) [0xb750682c]
/usr/sbin/mysqld(+0x4cde5f) [0xb756ae5f]
/usr/sbin/mysqld(row_ins+0x157) [0xb756d3c7]
/usr/sbin/mysqld(row_ins_step+0x110) [0xb756d710]
/usr/sbin/mysqld(row_insert_for_mysql+0x37e) [0xb75754de]
/usr/sbin/mysqld(ha_innobase::write_row(无符号字符*)+0xf9)[0xb74e1299]
/usr/sbin/mysqld(handler::ha_write_row(unsigned char*)+0x6d)[0xb7412d3d]
/usr/sbin/mysqld(write_record(THD*、st_table*、st_copy_info*)+0x3ba)[0xb7391e2a]
/usr/sbin/mysqld(mysql_insert(THD*、TABLE_LIST*、List&、List >&、List&、List&、enum_duplicates、bool)+0x1122) [0xb73967c2]
/usr/sbin/mysqld(mysql_execute_command(THD*)+0xc85) [0xb7317c95]
/usr/sbin/mysqld(mysql_parse(THD*、char const*、unsigned int、char const**)+0x3ae) [0xb731f45e]
/usr/sbin/mysqld(Query_log_event::do_apply_event(Relay_log_info const*,char const*,unsigned int)+0x47d)[0xb73dbe9d]
/usr/sbin/mysqld(Query_log_event::do_apply_event(Relay_log_info const*)+0x26)[0xb73dca76]
/usr/sbin/mysqld(apply_event_and_update_pos(Log_event*、THD*、Relay_log_info*)+0x137)[0xb7463cc7]
/usr/sbin/mysqld(handle_slave_sql+0x1094) [0xb74662e4]
/lib/tls/i686/cmov/libpthread.so.0(+0x596e) [0xb706396e]
/lib/tls/i686/cmov/libc.so.6(克隆+0x5e) [0xb6e29a4e]
尝试获取一些变量。
一些指针可能无效并导致转储中止......
thd->query 位于 0xb183bdc6 处,是一个无效指针
thd->线程ID=2
thd->killed=NOT_KILLED
http://dev.mysql.com/doc/mysql/en/crashing.html 上的手册页包含
这些信息应该可以帮助您找出导致崩溃的原因。

我一直在尝试各种选项,试图理解为什么它认为存在表不匹配。就我而言,应该不存在不匹配,因为我正在复制 ibdata1、innodb 日志文件以及 .ibd。那么为什么它不恢复并继续进行,以便我可以恢复复制?我显然遗漏了一些东西,但我找不到它。

任何线索或建议都值得赞赏。谢谢

答案1

我相信你有一个不一致的快照,特别是由于错误

InnoDB: Error: tablespace id is 150238 in the data dictionary  
InnoDB: but in file ./1_107789/email.ibd it is 150747!

这可能不是 LVM 的错。谷歌搜索这里这里,我猜你需要确保 mysql 已将所有内容写入磁盘(无缓冲区),并且不会通过锁定表来更改以确保安全。也可能是由于 MySQL 版本不同,innodb 代码中发生了一些变化。你可以在主服务器的克隆/(类似服务器)上尝试该精确快照来排除这种情况。请参阅这个也是

答案2

我认为问题出在我复制数据的方式上。由于我的旧从服务器上已经有一些数据库,所以我使用同步为了节省复制数据的时间:

/usr/bin/rsync -rtlP --inplace --delete /snapshot/var/lib/mysql another.host.com::root/var/lib/

但是由于我添加了 -I 选项,如下所示:

/usr/bin/rsync -rtlPI --inplace --delete /snapshot/var/lib/mysql another.host.com::root/var/lib/

它对我来说很有效。-I(--ignore-times)告诉 rsync“不要跳过大小和时间匹配的文件”。据推测,对文件进行的微小亚秒级更改(不会更改文件大小或文件时间戳)导致了问题。

相关内容