网易首页 > 网易号 > 正文 申请入驻

故障分析 | MySQL5.7 使用 mysqldump 重要闭坑事项

0
分享至

作者:王向
爱可生 DBA 团队成员,负责公司 DMP 产品的运维和客户 MySQL 问题的处理。擅长数据库故障处理。对数据库技术和 python 有着浓厚的兴趣。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

背景

笔者在一次处理客户 MySQL 问题时遇到客户的 MySQL 的 sys 库不能用了并抛出一下错误:

mysql> SELECT * FROM sys.processlist; ERROR 1356 (HY000): View 'sys.processlist' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them

首先,这个问题其实并不难解决,但是这个问题引发的现象倒是挺有意思。

排查常见问题

先定位几个常见问题:1. 权限不够;

2. sys 库 functions 和 procedures 丢失;

3. mysqldump 全备后跨版本恢复【会发生问题 2 的现象】;

4. mysql 升级没有执行 mysql_upgrade【会发生问题 2 的现象】;

首先排查权限问题是否有权限。

mysql> SHOW GRANTS FOR root@'localhost';+---------------------------------------------------------------------+| Grants for root@localhost |+---------------------------------------------------------------------+| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION || GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |+---------------------------------------------------------------------+2 rows in set (0.00 sec)

明显并不是,接着排查是否是 sys 库相关的 functions 和 procedures 丢失了?

mysql> SELECT * FROM mysql.proc;Empty set (0.00 sec)
mysql> SHOW PROCEDURE STATUS WHERE Db = 'sys';Empty set (0.00 sec)
mysql> SHOW FUNCTION STATUS WHERE Db = 'sys';Empty set (0.00 sec)

sys 库 functions 和 procedures 丢失了,那不就是问题 3 就是问题 4,甩给 mysqldump 全备和升级没有执行 mysql_upgrade。带着疑问于开始漫长的排查过程。经过对客户的刨根问题,发现并没有上述情况的发生。用户备份习惯都是全备(-A),且都是备份恢复后出现 sys 库 ERROR 1356,检查用户 MySQL 环境主要几大版本分布 MySQL 5.7.13,5.7.25,5.7.28。于是把问题定位到了 mysqldump 的备份上。

先备份还原一把看看

笔者强烈认为是客户跨版本造成的,给客户来点证据。先验证一波同版本 MySQL 使用 mysqldump 全备恢复后,到底会不会出现 sys 库 ERROR 1356。备份前先检测一波 sys 库,确认完全 OK 后开整。

mysql> SELECT * FROM sys.version;+-------------+---------------+| sys_version | mysql_version |+-------------+---------------+| 1.5.2 | 5.7.31-log |+-------------+---------------+1 row in set (0.00 sec)
mysql> SELECT * FROM sys.processlist; ERROR 1356 (HY000): View 'sys.processlist' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
mysql> SELECT COUNT(*) FROM mysql.proc;+----------+| COUNT(*) |+----------+| 48 |+----------+1 row in set (0.00 sec)

使用我们经常用的那坨命令备份所有库。

mysqldump --all-databases --set-gtid-purged=OFF \--master-data=2 --single-transaction --routines \--events --triggers --max_allowed_packet=256M > all.sql

备份完毕后我们开始恢复数据。

mysql -uroot -S /tmp/mysql.sock < all.sql

恢复完毕后,检测一波 sys 库。

mysql> SELECT * FROM sys.processlist; ERROR 1356 (HY000): View 'sys.processlist' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
mysql> SELECT COUNT(*) FROM mysql.proc;+----------+| COUNT(*) |+----------+| 0 |+----------+1 row in set (0.00 sec)
mysql> SHOW PROCEDURE STATUS WHERE Db = 'sys';Empty set (0.00 sec)
mysql> SHOW FUNCTION STATUS WHERE Db = 'sys';Empty set (0.00 sec)

啪啪啪打脸,竟然同版本也会出现?那究竟是什么问题?

再看看其它版本

经过对 MySQL 5.7.13,5.7.21,5.7.25,5.7.28,5.7.31 等几个版本测试全备躺枪。奇怪的现象是他们唯一的共性就是无论怎么备份怎么还原只要使用了 --all-databases (-A) 就报 ERROR 1356。这不禁让笔者陷入了沉思。

寻找突破点

既然通用规律只有使用 --all-databases (-A) 会 ERROR 1356,那就看看他到底备份了什么东西。于是喊上同事一起 less 看了下,上下扫了两眼。突然发现:

1. 备份 SQL 文件里 DROP 掉了 mysql.proc

2. 后CREATE了一个新的 mysql.proc

3. LOCK TABLESUNLOCK TABLES 中间居然没有备份 CREATE ROUTINE 任何数据?这不就是相当于每次导入全备都给我一个没有任何 sys schema routines 的全新 mysql.proc 表?那这不就异常的尴尬?

---- Table structure for table `proc`--
DROP TABLE IF EXISTS `proc`;/*!40101 SET @saved_cs_client = @@character_set_client */;/*!40101 SET character_set_client = utf8 */;CREATE TABLE `proc` ( `db` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `name` char(64) NOT NULL DEFAULT '', `type` enum('FUNCTION','PROCEDURE') NOT NULL, `specific_name` char(64) NOT NULL DEFAULT '', `language` enum('SQL') NOT NULL DEFAULT 'SQL', `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL DEFAULT 'CONTAINS_SQL', `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', `param_list` blob NOT NULL, `returns` longblob NOT NULL, `body` longblob NOT NULL, `definer` char(93) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `body_utf8` longblob, PRIMARY KEY (`db`,`name`,`type`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures';/*!40101 SET character_set_client = @saved_cs_client */;
---- Dumping data for table `proc`--
LOCK TABLES `proc` WRITE;/*!40000 ALTER TABLE `proc` DISABLE KEYS */;/*!40000 ALTER TABLE `proc` ENABLE KEYS */;UNLOCK TABLES;

真相大白

在官方文档【sys-schema-usage】https://dev.mysql.com/doc/refman/5.7/en/sys-schema-usage.html 页面有这样一段话(这里直接引用官方原文):However, those statements display the definitions in relatively unformatted form. To view object definitions with more readable formatting, access the individual .sql files found under the scripts/sys_schema in MySQL source distributions. Prior to MySQL 5.7.28, the sources are maintained in a separate distribution available from the sys schema development website at https://github.com/mysql/mysql-sys.Neither mysqldump nor mysqlpump dump the sys schema by default. To generate a dump file, name the sys schema explicitly on the command line using either of these commands:

sys:
https://dev.mysql.com/doc/refman/5.7/en/sys-schema.html
mysqldump:
https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html

mysqldump --databases --routines sys > sys_dump.sqlmysqlpump sys > sys_dump.sql

To reinstall the schema from the dump file, use this command:

mysql < sys_dump.sql

官方文档明确的告诉我们不会备份 sys 库。但在使用 mysqldump 在执行 --all-databases 会清空 mysql.proc 导致 sys 无法正常使用;这是一个 BUG,并且只存在于 MySQL 5.7.x !

BUG 连接:

  • https://bugs.mysql.com/bug.php?id=86807

  • https://bugs.mysql.com/bug.php?id=92631

  • https://bugs.mysql.com/bug.php?id=83259

  • https://github.com/mysql/mysql-server/commit/ded3155def2ba3356017c958c49ff58c2cae1830

解决方案和使用场景

针对这个 BUG 整理了 4 个解决方案可供参考,根据实际环境场景进行选择使用。

1、mysql_upgrade install or upgrade sys schema

这个方案适用于 sys 库已经因为 mysqldump 导入而损坏的情况下使用。

# 删除 sys schema (An error occurs if a sys schema exists but has no version view)mysql> DROP DATABASE sys;
# 这个时候 sys schema 不应该存在mysql> SHOW DATABASES;
# 最后,执行 mysql_upgrade sys schema 以恢复正常mysql_upgrade --upgrade-system-tables --skip-verbose --force
mysql> SHOW DATABASES;mysql> SELECT COUNT(*) FROM mysql.proc;

注意:mysql_upgrade 在修理 sys 库的同时,还修理 mysql 库和用户库表(期间加锁且速度一般),有极小可能会误伤;使用 mysql_upgrade 的时候要加上 --upgrade-system-tables,不然会扫描用户库表。

2、全备时同时备份 sys 库

这个方案适用于需要还原的数据库,sys 库也不太正常的情况下使用;在全备后额外再备份一份 sys 库用于修复。

mysqldump -A --set-gtid-purged=OFF --master-data=2 --single-transaction --routines --events --triggers > all.sqlmysqldump --databases --routines sys > sys_dump_`mysql -V|awk '{print $5}'|cut -b 1-6`.sql注意:不适用于做主从时使用它。

3、使用 databases 全备

这个方案适用于所有场景的全备需求,100% 安全。

select_databases=" SELECT GROUP_CONCAT(schema_name SEPARATOR ' ') FROM information_schema.schemata WHERE schema_name NOT IN ('performance_schema','information_schema');"
databases=`mysql -NBe "$select_databases"`mysqldump --set-gtid-purged=OFF --master-data=2 \--single-transaction --routines --events --triggers \--max_allowed_packet=256M --databases > all.sql

4、使用 mysql-sys 开源代码

如果你的数据库 sys 全部中招了,又是生产库。那你只能用这个方法;

mysql-sys:
https://github.com/mysql/mysql-sys

中记录了 sys 库的创建语句将文件下载到本地,然后根据数据库版本,执行以下命令即可。

# 安装前操作,内容是禁用掉 sql_log_bin,不记录到日志中。mysql> source before_setup.sql
# 创建 sys 库,实际会调用其他文件夹中的 sql 语句# 来进行表、视图、存储过程、触发器的创建mysql> source sys_57.sql
# 安装后的操作,内容是将 sql_log_bin 恢复到操作前的状态mysql> source after_setup.sql

【加餐 1】试试 MySQL 8

测试 MySQL 8.0.0 至 MySQL 8.0.20 全系列不受影响,具体原因是从 MySQL 8.0.0 起就移除了 mysql.proc 这张表。具体查阅官方文档:

1. data-dictionary-usage-differences:
https://dev.mysql.com/doc/refman/8.0/en/data-dictionary-usage-differences.html
2. news-8-0-0:
https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-0.html

Previously, tables in the mysql system database were visible to DML and DDL statements. As of MySQL 8.0, data dictionary tables are invisible and cannot be modified or queried directly. However, in most cases there are corresponding INFORMATION_SCHEMA tables that can be queried instead. This enables the underlying data dictionary tables to be changed as server development proceeds, while maintaining a stable INFORMATION_SCHEMA interface for application use.

【加餐 2】如果还有疑问?

那就顺便看一眼 mysqldump 的源码吧(这个源码的设计也挺有意思,准备放到后面的文章里面),先过一眼这个变量。

/** First mysql version supporting the information schema.*/#define FIRST_INFORMATION_SCHEMA_VERSION 50003/** Name of the information schema database.*/#define INFORMATION_SCHEMA_DB_NAME "information_schema"/** First mysql version supporting the performance schema.*/#define FIRST_PERFORMANCE_SCHEMA_VERSION 50503/** Name of the performance schema database.*/#define PERFORMANCE_SCHEMA_DB_NAME "performance_schema"
/** First mysql version supporting the sys schema.*/#define FIRST_SYS_SCHEMA_VERSION 50707 /* 最早出现sys schema的MySQL版本 5.7.7 */
/** Name of the sys schema database.*/#define SYS_SCHEMA_DB_NAME "sys"

dump 所有库表(--all-databases)的源码:

........./* 执行dump_all_databases的条件 */if (opt_alldbs) { if (!opt_alltspcs && !opt_notspcs) dump_all_tablespaces(); dump_all_databases(); }......... /* dump_all_databases */static int dump_all_databases(){ MYSQL_ROW row; MYSQL_RES *tableres; int result=0
/* 获取所有数据库:SHOW DATABASES */ if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES")) return 1; while ((row= mysql_fetch_row(tableres))) { /* 排除information_schema */ if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME)) continue; /* 排除performance_schema */ if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME)) continue; /* 排除sys */ /* 检查当前MySQL的版本是否 >= 最早支持SYS_SCHEMA的版本号。&& row[0] 为 SYS_SCHEMA_DB_NAME 就跳过,不进行备份*/ if (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION && !my_strcasecmp(&my_charset_latin1, row[0], SYS_SCHEMA_DB_NAME)) continue;
if (is_ndbinfo(mysql, row[0])) continue; /* dump库中所有表 */ /* 逐一dump每个表 dump_all_tables_in_db */ if (dump_all_tables_in_db(row[0])) result=1; }.........

备份 functions 和 procedures 的源码:

/** 此处 --all-databases sys 库不会传入 dump_routines_for_db 这个函数。 所以函数里面的备份过程跳过了sys库,也就造成了.sql文件里mysql.proc没有CREATE ROUTINE sys库的现象 */static uint dump_routines_for_db(char *db) {........ /* 0, retrieve and dump functions, 1, procedures */ for (i= 0; i <= 1; i++) { /* 执行SHOW FUNCTION/PROCEDURE STATUS WHERE Db = xx,获取所有functions和procedures */ my_snprintf(query_buff, sizeof(query_buff), "SHOW %s STATUS WHERE Db = '%s'", routine_type[i], db_name_buff);
if (mysql_query_with_error_report(mysql, &routine_list_res, query_buff)) DBUG_RETURN(1);
if (mysql_num_rows(routine_list_res)) {
while ((routine_list_row= mysql_fetch_row(routine_list_res))) { routine_name= quote_name(routine_list_row[1], name_buff, 0); DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i], name_buff)); /* 执行SHOW CREATE FUNCTION/PROCEDURE xxx,获取所有functions、procedures创建语句 */ my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s", routine_type[i], routine_name);........

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
超人这个动漫角色的来历?(附女超人图案)

超人这个动漫角色的来历?(附女超人图案)

祝晓塬
2024-05-13 15:22:47
不会汉语的菲律宾留学生获北大47万奖学金!每月2500元补助!

不会汉语的菲律宾留学生获北大47万奖学金!每月2500元补助!

泸沽湖
2024-05-16 10:32:41
喜讯!杨晨刚接手河南队就敲定重量级强援加盟,曾是冠军豪门核心

喜讯!杨晨刚接手河南队就敲定重量级强援加盟,曾是冠军豪门核心

罗掌柜体育
2024-05-19 19:53:01
7连号重出江湖!双色球第24056期晒票:人生总有不期而遇的温暖!

7连号重出江湖!双色球第24056期晒票:人生总有不期而遇的温暖!

双色球的方向舵
2024-05-19 19:01:57
“北上广”打工人的外卖:高碳水、重油重辣、多肉订单约占5成

“北上广”打工人的外卖:高碳水、重油重辣、多肉订单约占5成

澎湃新闻
2024-05-18 21:36:29
2023,设计杀害女友的军二代被注射死刑,细节露出:临终浑身颤抖

2023,设计杀害女友的军二代被注射死刑,细节露出:临终浑身颤抖

古书记史
2024-05-18 19:25:03
俄外长:俄愿与西方在平等条件下进行对话

俄外长:俄愿与西方在平等条件下进行对话

新华社
2024-05-18 22:54:06
TA记者:张康阳说法很奇怪,欠了钱就该还&苏宁还钱问题就能解决

TA记者:张康阳说法很奇怪,欠了钱就该还&苏宁还钱问题就能解决

直播吧
2024-05-18 21:17:19
八路军夜袭阳明堡机场,战果如何,日本史料的记载令人吃惊

八路军夜袭阳明堡机场,战果如何,日本史料的记载令人吃惊

老黄有话
2024-05-10 08:00:02
女子停车堵路口,打80个电话不接引发众怒,被打到生活不能自理

女子停车堵路口,打80个电话不接引发众怒,被打到生活不能自理

艾美讲故事
2024-05-08 15:01:36
名校校长的"后宫":88名女教师,霸占87人?!

名校校长的"后宫":88名女教师,霸占87人?!

北国向锡安
2024-05-11 09:55:37
罕见!马宁判海港四进球无效,西海岸越位进球有效,央视被迫打脸

罕见!马宁判海港四进球无效,西海岸越位进球有效,央视被迫打脸

邮轮摄影师阿嗵
2024-05-19 00:21:39
菲律宾海警扣押7名我国船员,马科斯要来硬的:日本急送5艘巡逻舰

菲律宾海警扣押7名我国船员,马科斯要来硬的:日本急送5艘巡逻舰

文雅笔墨
2024-05-19 17:29:07
如果把外国名字直接翻译过来,究竟有多土?

如果把外国名字直接翻译过来,究竟有多土?

牛锅巴小钒
2024-05-14 07:20:03
iOS/iPadOS 17.5 “照片复活门”升级:二手设备可显示原机主照片

iOS/iPadOS 17.5 “照片复活门”升级:二手设备可显示原机主照片

IT之家
2024-05-18 09:57:08
香港“四大怪菜”,都是本地人的心头爱,外地人直呼:下不去嘴

香港“四大怪菜”,都是本地人的心头爱,外地人直呼:下不去嘴

吃货的分享
2024-05-18 07:55:17
谁是我的菜

谁是我的菜

娱乐的小灶
2024-05-18 15:15:36
2000年,张学良来到赵四的病房,医生问他是否拔管,他示意拔掉

2000年,张学良来到赵四的病房,医生问他是否拔管,他示意拔掉

黎庶文史
2024-05-18 23:46:33
普京刚从中国回去,王毅和拉夫罗夫,又约好了新一轮见面对表

普京刚从中国回去,王毅和拉夫罗夫,又约好了新一轮见面对表

影剧真知岛
2024-05-18 16:10:22
最新女排积分榜!日本跌至第5,中国女排甩开积分差距,奥运有戏

最新女排积分榜!日本跌至第5,中国女排甩开积分差距,奥运有戏

开心体育站
2024-05-19 13:03:58
2024-05-19 21:10:44
爱可生云数据库
爱可生云数据库
企业数据处理技术整体解决方案
411文章数 20关注度
往期回顾 全部

科技要闻

雷军直播开车2000万人围观!突然遭别车

头条要闻

被传"随便捡"稻虾基地负责人:有很多人被逮到不止一次

头条要闻

被传"随便捡"稻虾基地负责人:有很多人被逮到不止一次

体育要闻

欧文:我尽力不哭出来 我们还要走很远

娱乐要闻

《庆余年2》首播口碑出炉!有好有坏

财经要闻

洞庭湖区非法采砂 2000余亩洲滩被挖空

汽车要闻

智驾升级/月底上市 问界新M7 MAX焕新版

态度原创

教育
手机
本地
家居
公开课

教育要闻

国风雅韵,承古启新——青岛第五十三中学2024年历史园游会侧记

手机要闻

充满爱意的 520 ,不妨用 iPhone 来记录

本地新闻

博物馆的正确打开方式|来河南,沉浸式体验中原文明

家居要闻

遇见交响 音乐流动在设计之中

公开课

父亲年龄越大孩子越不聪明?

无障碍浏览 进入关怀版