数据库内核月报 - 2015 / 05-MySQL · 捉虫动态 · 5.6 与 5.5 InnoDB 不兼容导致 crash

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

bug 背景

RDS的备份工具用的是 Percona-XtraBackup(后面简称PXB),这个工具包里有2个重要的工具,innobackupex和xtrabackup,后者是C编译出的二进制文件,负责备份 InnoDB 数据,前者是一个Perl 脚本,对后者进行封装,同时负责备份非 InnoDB 数据。xtrabackup 二进制里内嵌了InnoDB引擎,所以能很好的处理InnoDB数据。在2.2版本之前,PXB 分别针对不同版本的 MySQL 源码(5.1/5.5/5.6)编译了不同版本的xtrabackup,以便备份不同版本的MySQL数据,然而在2.2之后,PXB官方觉得5.6已经可以很好的兼容5.1和5.5,所以就只针对 5.6.22 版本的代码编译了一个 xtrabackup 二进制文件,关于这个改动可以看官方的BP #single binary。故事就由此发生。。。

bug 描述

当我们对5.5版本的备份集进行还原的时候,xtrabackup crash 了,报错信息如下:

2015-05-12 19:03:08 7fd9d8258720  InnoDB: Assertion failure in thread 140573610968864 in file pars0pars.cc line 865
InnoDB: Failing assertion: sym_node->table != NULL
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
11:03:08 UTC - xtrabackup got signal 6 ;
This could be because you hit a bug or data is corrupted.
This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

Thread pointer: 0x176aeb0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0 thread_stack 0x10000
xtrabackup(my_print_stacktrace+0x35) [0x9f5331]
xtrabackup(handle_fatal_signal+0x2bb) [0x7f801b]
/lib64/libpthread.so.0() [0x3530c0f500]
/lib64/libc.so.6(gsignal+0x35) [0x35f40328a5]
/lib64/libc.so.6(abort+0x175) [0x35f4034085]
xtrabackup() [0x76bfb0]
xtrabackup(pars_update_statement(upd_node_t*, sym_node_t*, void*)+0x30) [0x76c8d8]
xtrabackup(yyparse()+0xcb1) [0xa5ef27]
xtrabackup(pars_sql(pars_info_t*, char const*)+0xaf) [0x76e06d]
xtrabackup(que_eval_sql(pars_info_t*, char const*, unsigned long, trx_t*)+0x85) [0x78eeb2]
xtrabackup(row_drop_table_for_mysql(char const*, trx_t*, bool, bool)+0xa98) [0x720a0c]
xtrabackup(row_mysql_drop_temp_tables()+0x24c) [0x721503]
xtrabackup(recv_recovery_rollback_active()+0x2c) [0x753ebe]
xtrabackup(innobase_start_or_create_for_mysql()+0x17aa) [0x7293c4]
xtrabackup() [0x607a00]
xtrabackup() [0x610204]
xtrabackup(main+0x8b8) [0x611674]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x35f401ecdd]
xtrabackup() [0x604369]

## bug 分析
从crash的信息InnoDB: Assertion failure in thread 140573610968864 in file pars0pars.cc line 865,可以定位的crash的代码点

862|                sym_node->table = dict_table_open_on_name(
863|                        sym_node->name, TRUE, FALSE, DICT_ERR_IGNORE_NONE);
864|
865|                ut_a(sym_node->table != NULL);

可以看到,是 InnoDB 在试图打开一张表的时候,打开失败,直接 assert 了。

分析调用堆栈,是xtrabackup在恢复数据的时候,启动了内嵌的 InnoDB 引擎,在活跃事务回滚的时候,会将备份时候存在的临时表全部 drop 掉。在删除表的时候,除了要删除表本身,还需要删除在 InnoDB 系统表中的记录,删除记录是通过内部执行sql的方式做的que_eval_sql,其中有这么一段sql

4195|                           "DELETE FROM SYS_TABLESPACES\n"
4196|                           "WHERE SPACE = space_id;\n"
4197|                           "DELETE FROM SYS_DATAFILES\n"
4198|                           "WHERE SPACE = space_id;\n"

SYS_TABLESPACES 和 SYS_DATAFILES 这2个系统表是在5.6中才有的,5.5是没有的,所以在调用 dict_table_open_on_name 的时候就打不开 SYS_TABLESPACES 表,导致CRASH。

bug修复

这里给一个简单的修复方法,就是在调用 que_eval_sql 删除记录前判断下当前数据是否是5.6的,如果是就传原来的sql,如果不是,就传去掉 SYS_TABLESPACES 和 SYS_DATAFILES 的sql。PXB官方已经确认这个bug #1399471,目前尚未修复,应该会在下个版本修掉。
如果等不及的话,可以有2种选择:
1. 代码修复,用这里提供的方法;
2. 版本回退,在恢复的时候,临时用PXB 2.1版本中的 xtrabackup_55 替换 xtrabckup。

bug 影响

从上面的分析可以得到,要触发这个bug,需要这些条件:
1. PXB版本是2.2以上
2. MySQL版本是5.5/5.1
3. 备份的时候有持有临时表的回话。

当满足上面这些条件,恢复数据就会crash。

PXB备份出来的idb数据时间点是不一致的,恢复数据时需要应用redo将数据追到一个一致的点,效果上就相当于 MySQL 异常关闭,buffer pool 有数据没有落盘,然后重启应用redo做崩溃恢复。所以这个场景只有在用PXB才容易出现,对正常使用的mysqld来说一般是不会的,因为我们在升级的时候都是正常关闭 mysqld,这是临时表都被清理干净了,后再用新版mysqld启动,所以新版mysqld启动时就不需要做drop临时表的操作,自然不会crash了。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4天前
|
关系型数据库 MySQL 分布式数据库
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
《MySQL 简易速速上手小册》第6章:MySQL 复制和分布式数据库(2024 最新版)
34 2
|
2天前
|
SQL 存储 关系型数据库
数据库开发之mysql前言以及详细解析
数据库开发之mysql前言以及详细解析
10 0
|
6天前
|
SQL NoSQL 关系型数据库
初识MySQL数据库——“MySQL数据库”
初识MySQL数据库——“MySQL数据库”
|
9天前
|
关系型数据库 MySQL 数据库
数据库基础(mysql)
数据库基础(mysql)
|
9天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
33 3
|
10天前
|
存储 关系型数据库 MySQL
【后端面经】【数据库与MySQL】为什么MySQL用B+树而不用B树?-02
【4月更文挑战第11天】数据库索引使用规则:`AND`用`OR`不用,正用反不用,范围中断。索引带来空间和内存代价,包括额外磁盘空间、内存占用和数据修改时的维护成本。面试中可能涉及B+树、聚簇索引、覆盖索引等知识点。MySQL采用B+树,因其利于范围查询和内存效率。数据库不使用索引可能因`!=`、`LIKE`、字段区分度低、特殊表达式或全表扫描更快。索引与NULL值处理在不同数据库中有差异,MySQL允许NULL在索引中的使用。
16 3
|
11天前
|
关系型数据库 MySQL 数据库连接
Django(四):Django项目部署数据库及服务器配置详解(MySQL)
Django(四):Django项目部署数据库及服务器配置详解(MySQL)
34 11
|
20天前
|
SQL 数据可视化 关系型数据库
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
104 0
|
20天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
|
20天前
|
关系型数据库 MySQL 数据库
轻松入门MySQL:精准查询,巧用WHERE与HAVING,数据库查询如虎添翼(7)
轻松入门MySQL:精准查询,巧用WHERE与HAVING,数据库查询如虎添翼(7)

相关产品

  • 云数据库 RDS MySQL 版