运维管理7 分钟阅读
困扰 MySQL 用户多年的问题,它只用一个插件就解决了!
@TOC目录 上周有个朋友问我:"哥,我们刚从 MySQL 8.0 迁到金仓数据库的 MySQL 兼容模式,发现一个很神奇的 BUG"! 当我在金仓数据库中新建了一个用户以及表,没有对这个用户授权该表的访问权限,但是可以在 sysclass 表中查询到这个表的信息。
2025年11月19日阅读—点赞—收藏—
mysql
在知识库中专注阅读,并随时返回相关工具与课程
@TOC目录 上周有个朋友问我:"哥,我们刚从 MySQL 8.0 迁到金仓数据库的 MySQL 兼容模式,发现一个很神奇的 BUG"! 当我在金仓数据库中新建了一个用户以及表,没有对这个用户授权该表的访问权限,但是可以在 sysclass 表中查询到这个表的信息。
本章目标:掌握本章核心知识点 前置要求:完成前序章节学习 预计时长:60 分钟
上周有个朋友问我:"哥,我们刚从 MySQL 8.0 迁到金仓数据库的 MySQL 兼容模式,发现一个很神奇的 BUG"!
当我在金仓数据库中新建了一个用户以及表,没有对这个用户授权该表的访问权限,但是可以在 sys_class 表中查询到这个表的信息。

也就是说,即使用户没有表的访问权限,也能从系统表(sys_class)查询到该表的存在和元数据信息,这是金仓数据库的 BUG 还是 MySQL 原来就存在这种问题呢?
其实,这既不是金仓的 BUG,也不是 MySQL 的 BUG,而是一个长期存在的数据库安全设计问题。 值得一提的是,金仓数据库在近期将会发布一个新的功能插件 security_utils,针对这个问题进行修复,避免元数据的泄露问题,也是对 MySQL 兼容模式的安全增强!
我这里也是申请到了内测版的安装包,本文将演示一下如何使用 security_utils 插件进行用户的权限隔离,避免元数据泄露!
MySQL 数据库确实存在元数据泄露的问题:
1-- 即使用户没有权限,也能查询到表的存在2 mysql> SELECT table_name FROM information_schema.tables3 WHERE table_schema = 'mydb';4 +------------+5 | table_name |6 +------------+7 | orders |8 | customers |9 | salaries | -- 工资表,敏感!10 +------------+这是 MySQL 的默认设计,不是 BUG,但确实是安全隐患。从 MySQL 5.x 版本到 MySQL 8.0+ 版本都有相关的改进:
但注意:即使 MySQL 8.0,默认仍可通过 SHOW TABLES 或 information_schema 查看未授权表的名称。
正如开头的朋友所说,金仓数据库也是存在这种设计问题,下面我用一个例子进行还原。
首先,创建一个表以及用户:
1kingbase=# CREATE TABLE orders (2order_id INT PRIMARY KEY,3customer_id INT,4amount DECIMAL(10,2),5order_date DATE);67kingbase=# INSERT INTO orders VALUES8(1, 1001, 5999.00, '2024-11-01'),9(2, 1002, 3299.00, '2024-11-15');1011kingbase=# CREATE USER finance with password 'Finance@123';切换到 finance 用户查询:
1kingbase=# \c - finance2用户 finance 的口令:3您现在以用户名"finance"连接到数据库"kingbase"。4kingbase=> select oid,relname from sys_class where relname='orders';5 oid | relname6-------+---------7 16644 | orders89kingbase=> select * from orders;10ERROR: permission denied for table orders1112kingbase=> \dt13 关联列表14 架构模式 | 名称 | 类型 | 拥有者15----------+--------+--------+--------16 public | orders | 数据表 | system1718kingbase=> \d orders19 数据表 "public.orders"20 栏位 | 类型 | 校对规则 | 可空的 | 预设21-------------+---------------+----------+----------+------22 order_id | integer | | not null |23 customer_id | integer | | |24 amount | numeric(10,2) | | |25 order_date | date | | |26索引:27 "orders_pkey" PRIMARY KEY, btree (order_id NULLS FIRST)可以发现,此时 finance 用户并没有表 orders 的访问权限,但是仍然可以通过 sys_class 查看到 orders 表的元数据,甚至是表结构,这是十分不安全。
金仓数据库提供用户权限隔离功能,用户权限隔离功能开启后,普通用户只能查看有权访问的对象(表、函数、视图、字段等)。
用户权限隔离功能开启需要加载插件 security_utils,在使用 security_utils 之前,我们需要将他添加到 kingbase.conf 文件的 shared_preload_libraries 中,并重启 KingbaseES 数据库:
1shared_preload_libraries = 'security_utils'
重启数据库生效:
1[kingbase@kesv9:/install]$ sys_ctl restart -D /data/2等待服务器进程关闭 .... 完成3服务器进程已经关闭4等待服务器进程启动 ....2025-08-27 00:08:29.862 CST [93180] LOG: config the real archive_command string as soon as possible to archive WAL files52025-08-27 00:08:29.869 CST [93180] LOG: sepapower extension initialized62025-08-27 00:08:29.903 CST [93180] LOG: starting KingbaseES V009R003C01272025-08-27 00:08:29.903 CST [93180] LOG: listening on IPv4 address "0.0.0.0", port 5432182025-08-27 00:08:29.903 CST [93180] LOG: listening on IPv6 address "::", port 5432192025-08-27 00:08:29.905 CST [93180] LOG: listening on Unix socket "/tmp/.s.KINGBASE.54321"102025-08-27 00:08:29.986 CST [93180] LOG: redirecting log output to logging collector process112025-08-27 00:08:29.986 CST [93180] HINT: Future log output will appear in directory "sys_log".12 完成13服务器进程已经启动开启权限隔离功能:
1kingbase=# \c - system2您现在以用户名"system"连接到数据库"kingbase"。3-- 开启功能4kingbase=# create extension kdb_schedule;5CREATE EXTENSION6kingbase=# create extension security_utils;7CREATE EXTENSION至此,用户隔离的插件已开启。
接下来,演示一下 Kingbase MySQL 兼容模式如何进行用户权限隔离。
数据库级别开启用户权限隔离:
1kingbase=> \c - system2用户 system 的口令:3您现在以用户名"system"连接到数据库"kingbase"。4kingbase=# alter database kingbase enable object isolation;5ALTER DATABASE再切换到 finance 用户查询:
1kingbase=# \c - finance2用户 finance 的口令:3您现在以用户名"finance"连接到数据库"kingbase"。4kingbase=> select oid,relname from sys_class where relname='orders';5 oid | relname6-----+---------7(0 行记录)89kingbase=> \dt10Did not find any relations.11kingbase=> \d orders12Did not find any relation named "orders".已经无法查询到 sys_class 中 orders 表的信息,包括元数据以及表结构,都已经无法查看。
如果想要访问以上元数据,则需要人为进行授权该表给用户才行:
1kingbase=> \c - system2用户 system 的口令:3您现在以用户名"system"连接到数据库"kingbase"。4kingbase=# grant select on table orders to finance;5GRANT再切换到 finance 用户查询:
1kingbase=# \c - finance2用户 finance 的口令:3您现在以用户名"finance"连接到数据库"kingbase"。4kingbase=> select oid,relname from sys_class where relname='orders';5 oid | relname6-------+---------7 16644 | orders8(1 行记录)910kingbase=> \dt11 关联列表12 架构模式 | 名称 | 类型 | 拥有者13----------+--------+--------+--------14 public | orders | 数据表 | system15(1 行记录)1617kingbase=> \d orders18 数据表 "public.orders"19 栏位 | 类型 | 校对规则 | 可空的 | 预设20-------------+---------------+----------+----------+------21 order_id | integer | | not null |22 customer_id | integer | | |23 amount | numeric(10,2) | | |24 order_date | date | | |25索引:26 "orders_pkey" PRIMARY KEY, btree (order_id NULLS FIRST)可以发现,金仓数据库通过插件方式实现了开关式的一键开关用户权限隔离功能,十分方便快捷。
金仓数据库的这个功能,技术底层实现依赖 行级安全策略(Row-Level Security, RLS),通过修改数据库状态,为当前数据库具有 ACL 字段的系统表统一添加配置好的 RLS,通过 RLS 筛选以实现普通用户只能查看有权访问的对象(表、函数、视图、字段等)的目的。
在数字化时代,数据安全至关重要,数据库权限管理是核心保障。金仓数据库通过 security_utils 插件提供了超越 MySQL 原生能力的安全特性,补齐了 Oracle 级别的安全特性,通过插件化实现,兼顾灵活性和安全性。
同时,金仓数据库高度兼容 MySQL 的语法与基本功能,降低应用迁移成本,还在权限管理上实现功能增强,能满足金融、医疗等领域复杂需求,为企业数字化转型提供可靠数据安全支撑。