困扰 MySQL 用户多年的问题,它只用一个插件就解决了!

前言

上周有个朋友问我:“哥,我们刚从 MySQL 8.0 迁到金仓数据库的 MySQL 兼容模式,发现一个很神奇的 BUG”!

当我在金仓数据库中新建了一个用户以及表,没有对这个用户授权该表的访问权限,但是可以在 sys_class 表中查询到这个表的信息。

也就是说,即使用户没有表的访问权限,也能从系统表(sys_class)查询到该表的存在和元数据信息,这是金仓数据库的 BUG 还是 MySQL 原来就存在这种问题呢?

其实,这既不是金仓的 BUG,也不是 MySQL 的 BUG,而是一个长期存在的数据库安全设计问题。 值得一提的是,金仓数据库在近期将会发布一个新的功能插件 security_utils,针对这个问题进行修复,避免元数据的泄露问题,也是对 MySQL 兼容模式的安全增强!

我这里也是申请到了内测版的安装包,本文将演示一下如何使用 security_utils 插件进行用户的权限隔离,避免元数据泄露!

MySQL 数据库

MySQL 数据库确实存在元数据泄露的问题:

-- 即使用户没有权限,也能查询到表的存在
  mysql> SELECT table_name FROM information_schema.tables
         WHERE table_schema = 'mydb';
  +------------+
  | table_name |
  +------------+
  | orders     |
  | customers  |
  | salaries   |  -- 工资表,敏感!
  +------------+

这是 MySQL 的默认设计,不是 BUG,但确实是安全隐患。从 MySQL 5.x 版本到 MySQL 8.0+ 版本都有相关的改进:

版本行为
MySQL 5.x所有用户可查看所有数据库的表结构
MySQL 8.0+引入部分隔离,但仍可探测表存在性

但注意:即使 MySQL 8.0,默认仍可通过 SHOW TABLESinformation_schema 查看未授权表的名称。

金仓数据库

正如开头的朋友所说,金仓数据库也是存在这种设计问题,下面我用一个例子进行还原。

首先,创建一个表以及用户:

kingbase=# CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
amount DECIMAL(10,2),
order_date DATE);

kingbase=# INSERT INTO orders VALUES
(1, 1001, 5999.00, '2024-11-01'),
(2, 1002, 3299.00, '2024-11-15');

kingbase=# CREATE USER finance with password 'Finance@123';

切换到 finance 用户查询:

kingbase=# \c - finance
用户 finance 的口令:
您现在以用户名"finance"连接到数据库"kingbase"。
kingbase=> select oid,relname from sys_class where relname='orders';
  oid  | relname
-------+---------
 16644 | orders

kingbase=> select * from orders;
ERROR:  permission denied for table orders

kingbase=> \dt
              关联列表
 架构模式 |  名称  |  类型  | 拥有者
----------+--------+--------+--------
 public   | orders | 数据表 | system

kingbase=> \d orders
                  数据表 "public.orders"
    栏位     |     类型      | 校对规则 |  可空的  | 预设
-------------+---------------+----------+----------+------
 order_id    | integer       |          | not null |
 customer_id | integer       |          |          |
 amount      | numeric(10,2) |          |          |
 order_date  | date          |          |          |
索引:
    "orders_pkey" PRIMARY KEY, btree (order_id NULLS FIRST)

可以发现,此时 finance 用户并没有表 orders 的访问权限,但是仍然可以通过 sys_class 查看到 orders 表的元数据,甚至是表结构,这是十分不安全。

加载插件

金仓数据库提供用户权限隔离功能,用户权限隔离功能开启后,普通用户只能查看有权访问的对象(表、函数、视图、字段等)。

用户权限隔离功能开启需要加载插件 security_utils,在使用 security_utils 之前,我们需要将他添加到 kingbase.conf 文件的 shared_preload_libraries 中,并重启 KingbaseES 数据库:

shared_preload_libraries = 'security_utils'

重启数据库生效:

[kingbase@kesv9:/install]$ sys_ctl restart -D /data/
等待服务器进程关闭 .... 完成
服务器进程已经关闭
等待服务器进程启动 ....2025-08-27 00:08:29.862 CST [93180] LOG:  config the real archive_command string as soon as possible to archive WAL files
2025-08-27 00:08:29.869 CST [93180] LOG:  sepapower extension initialized
2025-08-27 00:08:29.903 CST [93180] LOG:  starting KingbaseES V009R003C012
2025-08-27 00:08:29.903 CST [93180] LOG:  listening on IPv4 address "0.0.0.0", port 54321
2025-08-27 00:08:29.903 CST [93180] LOG:  listening on IPv6 address "::", port 54321
2025-08-27 00:08:29.905 CST [93180] LOG:  listening on Unix socket "/tmp/.s.KINGBASE.54321"
2025-08-27 00:08:29.986 CST [93180] LOG:  redirecting log output to logging collector process
2025-08-27 00:08:29.986 CST [93180] HINT:  Future log output will appear in directory "sys_log".
 完成
服务器进程已经启动

开启权限隔离功能:

kingbase=# \c - system
您现在以用户名"system"连接到数据库"kingbase"-- 开启功能
kingbase=# create extension kdb_schedule;
CREATE EXTENSION
kingbase=# create extension security_utils;
CREATE EXTENSION

至此,用户隔离的插件已开启。

实战演示

接下来,演示一下 Kingbase MySQL 兼容模式如何进行用户权限隔离。

数据库级别开启用户权限隔离:

kingbase=> \c - system
用户 system 的口令:
您现在以用户名"system"连接到数据库"kingbase"。
kingbase=# alter database kingbase enable object isolation;
ALTER DATABASE

再切换到 finance 用户查询:

kingbase=# \c - finance
用户 finance 的口令:
您现在以用户名"finance"连接到数据库"kingbase"。
kingbase=> select oid,relname from sys_class where relname='orders';
 oid | relname
-----+---------
(0 行记录)

kingbase=> \dt
Did not find any relations.
kingbase=> \d orders
Did not find any relation named "orders".

已经无法查询到 sys_class 中 orders 表的信息,包括元数据以及表结构,都已经无法查看。

如果想要访问以上元数据,则需要人为进行授权该表给用户才行:

kingbase=> \c - system
用户 system 的口令:
您现在以用户名"system"连接到数据库"kingbase"。
kingbase=# grant select on table orders to finance;
GRANT

再切换到 finance 用户查询:

kingbase=# \c - finance
用户 finance 的口令:
您现在以用户名"finance"连接到数据库"kingbase"。
kingbase=> select oid,relname from sys_class where relname='orders';
  oid  | relname
-------+---------
 16644 | orders
(1 行记录)

kingbase=> \dt
              关联列表
 架构模式 |  名称  |  类型  | 拥有者
----------+--------+--------+--------
 public   | orders | 数据表 | system
(1 行记录)

kingbase=> \d orders
                  数据表 "public.orders"
    栏位     |     类型      | 校对规则 |  可空的  | 预设
-------------+---------------+----------+----------+------
 order_id    | integer       |          | not null |
 customer_id | integer       |          |          |
 amount      | numeric(10,2) |          |          |
 order_date  | date          |          |          |
索引:
    "orders_pkey" PRIMARY KEY, btree (order_id NULLS FIRST)

可以发现,金仓数据库通过插件方式实现了开关式的一键开关用户权限隔离功能,十分方便快捷。

金仓数据库的这个功能,技术底层实现依赖 行级安全策略(Row-Level Security, RLS),通过修改数据库状态,为当前数据库具有 ACL 字段的系统表统一添加配置好的 RLS,通过 RLS 筛选以实现普通用户只能查看有权访问的对象(表、函数、视图、字段等)的目的。

写在最后

在数字化时代,数据安全至关重要,数据库权限管理是核心保障。金仓数据库通过 security_utils 插件提供了超越 MySQL 原生能力的安全特性,补齐了 Oracle 级别的安全特性,通过插件化实现,兼顾灵活性和安全性。

同时,金仓数据库高度兼容 MySQL 的语法与基本功能,降低应用迁移成本,还在权限管理上实现功能增强,能满足金融、医疗等领域复杂需求,为企业数字化转型提供可靠数据安全支撑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lucifer三思而后行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值