mysql报错处理 View 'sys.xxx' references invalid table(s) or column(s) or function(s)

2022-10-11 10:21:18 浏览数 (2)

环境

使用巡检脚本巡检数据库的时候报错的.

mysql: 5.7.27 (如下教程为复现过程. mysql版本为:5.7.38)

报错

代码语言:txt复制
Process Process-2:
Traceback (most recent call last):
  File "/usr/lib64/python3.6/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib64/python3.6/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "/root/ddcw_inspection_v2.1/source/inspection/work_inspection.py", line 331, in inspection
    baseinfo['mem_total'] = data2['sys.memory_global_total']['data'].values[0][0]
AttributeError: 'DatabaseError' object has no attribute 'values'

处理过程

找到相关SQL

根据报错找到对应的代码是 select * from sys.memory_global_total. 此报错为无返回数据.

原因有2个:

  1. 无权限.
  2. 该视图有问题

排除无权限问题

查询sys.memory_global_total视图 需要查询权限和执行权限(含函数). 使用的用户含此权限, 故排除.

代码语言:txt复制
(root@127.0.0.1) [(none)]> show grants for 'u1'@'%';
 -------------------------------------------------------------- 
| Grants for u1@%                                              |
 -------------------------------------------------------------- 
| GRANT SELECT, EXECUTE, REPLICATION CLIENT ON *.* TO 'u1'@'%' |
 -------------------------------------------------------------- 

确认视图有问题

直接使用该用户登录mysql执行相关查询sql.

根据报错提示, 得出可能为: 1. 表或者字段 有问题. 2. 函数或者definer有问题

也就是这个视图有问题.

代码语言:txt复制
(u1@127.0.0.1) [(none)]> select * from sys.memory_global_total;
ERROR 1356 (HY000): View 'sys.memory_global_total' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them

根据DDL确定函数有问题

查询该视图的DDL, 得到sql: select sys.format_bytes(sum(performance_schema.memory_summary_global_by_event_name.CURRENT_NUMBER_OF_BYTES_USED)) AS total_allocated from performance_schema.memory_summary_global_by_event_name

代码语言:txt复制
show create table sys.memory_global_total;

手动执行该sql, 得到报错函数sys.format_bytes 不存在. 问题到这里就很清楚了. 接下来就是解决办法.

代码语言:txt复制
(u1@127.0.0.1) [(none)]> select `sys`.`format_bytes`(sum(`performance_schema`.`memory_summary_global_by_event_name`.`CURRENT_NUMBER_OF_BYTES_USED`)) AS `total_allocated` from `performance_schema`.`memory_summary_global_by_event_name`;
ERROR 1305 (42000): FUNCTION sys.format_bytes does not exist

解决办法

既然问题是函数sys.format_bytes不存在, 那解决办法就很多了.

  1. 重建sys库.
  2. 手动创建相关函数
  3. 使用mysql_upgrade修复.
  4. 从其它地方导出sys库, 然后导入到本实例(就是1)

本次使用第二种办法, 最快最简单. 找到该函数的DDL. (@@basedir/share/mysql_sys_schema.sql)

代码语言:javascript复制
CREATE DEFINER='mysql.sys'@'localhost' FUNCTION format_bytes ( bytes TEXT ) RETURNS TEXT COMMENT 'n Descriptionn n Takes a raw bytes value, and converts it to a human readable format.n n Parametersn n bytes (TEXT):n A raw bytes value.n n Returnsn n TEXTn n Examplen n mysql> SELECT sys.format_bytes(2348723492723746) AS size;n  ---------- n | size     |n  ---------- n | 2.09 PiB |n  ---------- n 1 row in set (0.00 sec)n n mysql> SELECT sys.format_bytes(2348723492723) AS size;n  ---------- n | size     |n  ---------- n | 2.14 TiB |n  ---------- n 1 row in set (0.00 sec)n n mysql> SELECT sys.format_bytes(23487234) AS size;n  ----------- n | size      |n  ----------- n | 22.40 MiB |n  ----------- n 1 row in set (0.00 sec)n ' SQL SECURITY INVOKER DETERMINISTIC NO SQL BEGIN IF bytes IS NULL THEN RETURN NULL; ELSEIF bytes >= 1125899906842624 THEN RETURN CONCAT(ROUND(bytes / 1125899906842624, 2), ' PiB'); ELSEIF bytes >= 1099511627776 THEN RETURN CONCAT(ROUND(bytes / 1099511627776, 2), ' TiB'); ELSEIF bytes >= 1073741824 THEN RETURN CONCAT(ROUND(bytes / 1073741824, 2), ' GiB'); ELSEIF bytes >= 1048576 THEN RETURN CONCAT(ROUND(bytes / 1048576, 2), ' MiB'); ELSEIF bytes >= 1024 THEN RETURN CONCAT(ROUND(bytes / 1024, 2), ' KiB'); ELSE RETURN CONCAT(ROUND(bytes, 0), ' bytes'); END IF; END//

验证:

代码语言:javascript复制
(u1@127.0.0.1) [(none)]> select * from sys.memory_global_total;
 ----------------- 
| total_allocated |
 ----------------- 
| 140.77 MiB      |
 ----------------- 

总结

sys库在升级的时候可能出现问题. 某些视图或者函数丢失之类的. 但不影响业务,一般也不会管...

本次的问题表面看起来是权限问题(没得权限的时候和这个报错一模一样...), 但是细细分析发现root用户也会报这个错. 然后查看DDL, 根据对应的sql去试下, 看报啥错, 然后解决.

其实每次报错都是有提示的. 跟着提示走就行.

0 人点赞