适用范围
MySQL5.7全系版本,所有平台(Linux,Windows,MacOS…)
问题概述
通过mysqldump全库导出数据进行恢复后sys库无法使用。
mysql> SELECT * FROM sys.processlist;
ERROR 1356 (HY000): View ’sys.processlist‘ references invalid tables(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
先定位几个可能的原因:
1,权限问题
2,sys库对象丢失
3,版本问题
4,mysql升级导致
问题排查
确认权限是否正确:
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)
--通过上面查询,表明用户权限没有问题,具有最高权限。
接着进行对象查询,排查对象是否存在
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 库 function 和 procedure 丢失了,丢失原因未知,怀疑是MySQL升级没有执行upgrade脚本导致
带着疑问继续排查,经过详细的追问客户和问询问题产生前发生的所有情况,发现并没有上述情况的发生。用户备份习惯都是全备(-A),且都是备份恢复后出现 sys 库 ERROR 1356,检查用户MySQL 环境主要几大版本分布 MySQL 5.7.13,5.7.25,5.7.28。于是把问题定位到了 mysqldump 的备份上,怀疑跨版本恢复造成,故先自己用相同版本模拟测试如下:
mysqldump --all-databases --set-gtid-purged=OFF --single-transaction --routines --events --triggers > 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相同版本备份恢复也会出现同样问题,经过对 MySQL 5.7.X等多个版本测试全部躺枪。奇怪的现象是:只要使用了 --all-databases (-A) 就报 ERROR 1356错误。
继续排查问题,我们从解读dump文件内容发现端倪:
- 备份文件中 DROP 掉了 mysql.proc;
- 后 CREATE 了一个新的 mysql.proc;
- LOCK TABLES 和 UNLOCK TABLES 中间没有备份 CREATE ROUTINE 任何数据!
---- 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 '',
......
......
-- 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中的 routine 数据都没有,为空。
问题原因
经过查找在官方文档中:
https://dev.mysql.com/doc/refman/5.7/en/sys-schema-usage.html
找出下面一段话

官方文档明确的告诉我们不会备份 sys 库。但在使用 mysqldump 在执行 --all-databases 会清空 mysql. proc 导致 sys 无法正常使用。
这是一个 BUG,并且只存在于 MySQL 5.7.x !
bugs链接:
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
解决方案
一,mysqldump备份导出数据时只导出业务数据库,不导出全部(包含数据字典信息)不使用–all-database 或者-A 参数
二,执行mysql_upgrade install or upgrade sys schema
mysql> DROP DATABASE sys;
mysql_upgrade --upgrade-system-tables --skip-verbose --force
mysql> SELECT COUNT(*) FROM mysql.proc;
+----------+
| COUNT(*) |
+----------+
| 49 |
+----------+
1 row in set (0.00 sec)
--注意:mysql_upgrade 在修复 sys 库的同时,还会修复mysql 库和用户库表(期间加锁且速度一般),有可能会收到影响;使用 mysql_upgrade 的时候要加上--upgrade-system-tables,不然会扫描用户库表。
三,全备同时再备份一下sys库
mysqldump -A --set-gtid-purged=OFF --single-transaction --routines -- events --triggers > all.sql
mysqldump --databases --routines sys > sys_dump.sql
--该方案不适合用在主从同步情况下
使用限制
- 该问题适用5.7全系版本
- MySQL8.0所有版本中没有此类问题
参考文档
https://dev.mysql.com/doc/refman/5.7/en/sys-schema-usage.html




