暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

【金仓产品体验官】:解锁 KingbaseES MySQL 兼容性 | 用户变量&事件调度器篇

原创 shunwahⓂ️ 2025-08-22
479

国产数据库的兼容性突围:金仓KingbaseES深度实测,用户变量与事件调度器表现惊艳!

个人简介
作者: ShunWah
公众号: “顺华星辰运维栈”主理人。

持有认证: OceanBase OBCA/OBCP、MySQL OCP、OpenGauss、崖山 DBCA、亚信 AntDBCA、翰高 HDCA、GBase 8a | 8c | 8s、Galaxybase GBCA、Neo4j Graph Data Science Certification、NebulaGraph NGCI & NGCP、东方通 TongTech TCPE 等多项权威认证。
获奖经历: 在OceanBase&墨天轮征文大赛、OpenGauss、TiDB、YashanDB、Kingbase、KWDB 征文等赛事中多次斩获一、二、三等奖,原创技术文章常年被墨天轮、CSDN、ITPUB 等平台首页推荐。

  • 公众号:顺华星辰运维栈
  • CSDN:shunwahma
  • 墨天轮:shunwah
  • ITPUB:shunwah

MySQL OCP 考试免费攻略 1.png

一、 引子:拥抱国产化浪潮,体验平替先锋

“2025金仓数据库产品体验官火热招募”的号角已然吹响,“数据库平替用金仓”的理念正席卷技术圈!作为国产数据库的领军力量,金仓数据库(KingbaseES)以其卓越的性能、高度的兼容性和完善的企业级特性,正成为众多关键业务系统从传统数据库(如 MySQL、Oracle)平滑迁移、安全可控的理想选择。本次“MySQL 兼容深度体验”第2期聚焦实战测评,我有幸作为体验官,将深入金仓数据库 V9 版本,围绕其核心的 PLMYSQL 兼容特性——特别是对 MySQL 用户变量事件调度器 (Event Scheduler) 的支持,进行从零开始的构建与深度测试,一探其兼容实力。

二、 体验环境准备

1、数据库环境准备

image.png

2、确认数据库类型和版本:

ecommerce_db=# SELECT version(); version ------------------------- KingbaseES V009R003C011 (1 row)

image.png

3、检查已安装的扩展:

ecommerce_db=# SELECT * FROM pg_extension; oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition -------+-----------------------+----------+--------------+----------------+------------+-----------+------------- 13276 | plpgsql | 10 | 11 | f | 1.0 | | 13278 | kdb_license | 10 | 11 | f | 1.1 | | 13280 | sysaudit | 10 | 13279 | f | 1.0 | | 13286 | src_restrict | 10 | 13285 | f | 1.0 | | 13289 | sysmac | 10 | 13288 | f | 1.0 | | 13297 | sys_anon | 10 | 13296 | f | 1.0 | | 13299 | sys_hm | 10 | 11 | f | 1.0 | | 13305 | kingbase_version | 10 | 11 | f | 1.1 | | 13541 | kdb_charbyte | 10 | 8000 | f | 1.0 | | 13840 | kdb_inherit_functions | 10 | 8000 | f | 1.5 | | 13860 | kdb_mysql_datatype | 10 | 11 | f | 1.7 | | 12125 | plmysql | 10 | 11 | f | 1.0 | | 12126 | kdb_mysql_functions | 10 | 8000 | t | 1.15 | | 12129 | kdb_cast | 10 | 8000 | f | 1.0 | | 12218 | sys_freespacemap | 10 | 8000 | t | 1.3 | | 12519 | xlog_record_read | 10 | 11 | t | 1.0 | | 12521 | sys_stat_statements | 10 | 2200 | t | 1.11 | | 12530 | kdb_tinyint | 10 | 11 | f | 1.0 | | (18 rows)

image.png

三、 实战第一步:构建基础——库与表的创建

兼容性的基石在于最基础的 DDL 操作。我们首先模拟一个典型的 MySQL 应用场景——创建一个电商相关的数据库和表。

1. 创建数据库

使用熟悉的 CREATE DATABASE 语法。

[kingbase@worker3 ~]$ ksql -U system -d test -p 54321 Password for user system: Licesen Type: SALES-企业版. Type "help" for help. test=# CREATE DATABASE ecommerce_db WITH ENCODING = 'UTF8'; CREATE DATABASE test=# \c ecommerce_db; You are now connected to database "ecommerce_db" as userName "system". ecommerce_db=#

image.png

执行顺畅,语法与 MySQL 完全兼容。

2. 创建核心业务表

创建一个 orders (订单表) 和一个 audit_log (审计日志表,用于后续事件调度器演示)。

2.1 创建订单表 (orders):
ecommerce_db=# CREATE TABLE orders ( ecommerce_db(# order_id SERIAL PRIMARY KEY, ecommerce_db(# customer_id INT NOT NULL, ecommerce_db(# order_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, ecommerce_db(# total_amount DECIMAL(10, 2) NOT NULL, ecommerce_db(# status VARCHAR(20) NOT NULL DEFAULT 'NEW' ecommerce_db(# ); CREATE TABLE

image.png

2.2 创建审计日志表 (audit_log):
ecommerce_db=# CREATE TABLE audit_log ( ecommerce_db(# log_id SERIAL PRIMARY KEY, ecommerce_db(# action VARCHAR(50) NOT NULL, -- 操作类型 (e.g., 'Order_Created', 'Status_Updated') ecommerce_db(# target_table VARCHAR(50) NOT NULL, -- 操作的目标表 ecommerce_db(# target_id INT, -- 操作记录的主键ID (如 order_id) ecommerce_db(# action_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, ecommerce_db(# performed_by VARCHAR(50) DEFAULT CURRENT_USER -- 执行操作的用户 ecommerce_db(# ); CREATE TABLE

image.png

表结构定义语法与 MySQL 高度一致。特别留意 SERIAL 类型,它在金仓 MySQL 兼容模式下完全模拟了 MySQL AUTO_INCREMENT 的行为。DEFAULT CURRENT_TIMESTAMPDEFAULT CURRENT_USER 等默认值表达式也完美支持。

3. 插入测试数据

3.1 插入一些订单数据:
ecommerce_db=# INSERT INTO orders (customer_id, total_amount, status) VALUES ecommerce_db-# (1001, 199.99, 'NEW'), ecommerce_db-# (1002, 349.50, 'PROCESSING'), ecommerce_db-# (1003, 55.00, 'COMPLETED'), ecommerce_db-# (1001, 78.90, 'NEW'); INSERT 0 4

image.png

3.2 插入一条审计日志示例:
ecommerce_db=# INSERT INTO audit_log (action, target_table, target_id) VALUES ('Initial_Setup', 'orders', NULL); INSERT 0 1

image.png

数据插入语法、VALUES 列表格式与 MySQL 无异,操作流畅。

四、 核心兼容特性深度测评:PLMYSQL 闪耀时刻

(一) MySQL 用户变量 (@varname) 兼容性测试

用户变量是 MySQL 中非常灵活的特性,用于在会话内存储临时值,常用于存储查询中间结果、跨语句传递数据或在存储过程中简化逻辑。金仓 PLMYSQL 对此提供了优秀的兼容。

测试场景 1:基础赋值与使用

1.1 – 设置用户变量
SET @customer_id := 1001; -- 使用 := 赋值 (兼容 MySQL 的 SET 语法) SET @discount_rate = 0.9; -- 使用 = 赋值 (也是兼容的)
ecommerce_db=# SET @customer_id := 1001; SET ecommerce_db=# SET @discount_rate = 0.9; SET

image.png

1.2 在查询中使用用户变量:
ecommerce_db=# SELECT * FROM orders WHERE customer_id = @customer_id; order_id | customer_id | order_date | total_amount | status ----------+-------------+---------------------+--------------+-------- 1 | 1001 | 2025-08-13 15:01:40 | 199.99 | NEW 4 | 1001 | 2025-08-13 15:01:40 | 78.90 | NEW (2 rows)

image.png

1.3 计算并存储新值:
ecommerce_db=# SELECT @max_amount := MAX(total_amount) FROM orders; @max_amount ------------- 349.50 (1 row) ecommerce_db=# SELECT @max_amount AS '最大订单金额'; 最大订单金额 -------------- 349.50 (1 row)

image.png

结果与分析: 变量赋值 (SET)、在 WHERE 子句和 SELECT 列表中使用变量均表现正常。查询结果准确返回了 customer_id=1001 的订单,并正确计算和显示了最大订单金额。语法和行为与 MySQL 完全一致。

测试场景 2:跨语句传递与更新

2.1 – 初始化一个计数器变量
SET @order_count := 0;
ecommerce_db=# SET @order_count := 0; SET

image.png

2.2 – 更新订单状态并计数 (假设只更新状态为 ‘NEW’ 的):
ecommerce_db=# UPDATE orders ecommerce_db-# SET status = 'PROCESSING' ecommerce_db-# WHERE status = 'NEW' ecommerce_db-# AND customer_id = @customer_id; UPDATE 2

image.png

2.3 – 获取受影响行数并累加到计数器:
ecommerce_db=# SET @order_count = @order_count + ROW_COUNT(); SET

image.png

2.4 – 显示处理了多少个新订单:
ecommerce_db=# SELECT @order_count AS '处理的新订单数'; 处理的新订单数 ---------------- 2 (1 row)

image.png

结果与分析: 此场景模拟了一个常见操作:使用变量计数。@order_count 成功在 UPDATE 语句后的 SET 语句中被更新,其值基于 ROW_COUNT() 函数(金仓也兼容此函数)累加。最终查询正确显示了处理的新订单数量。这证明了用户变量在同一个会话内的不同 SQL 语句间有效保持和传递数据的能力。

测试场景 3:在存储过程中使用用户变量 (PLMYSQL 体现)

虽然用户变量本身是会话级的,但在兼容 MySQL 的存储过程(PLMYSQL)中也能无缝使用。

3.1 – 步骤1:创建必要的表:
ecommerce_db=# CREATE TABLE IF NOT EXISTS order_status_summary ( ecommerce_db(# summary_id SERIAL PRIMARY KEY, ecommerce_db(# summary_date DATE NOT NULL, ecommerce_db(# status VARCHAR(20) NOT NULL, ecommerce_db(# order_count INT NOT NULL ecommerce_db(# ); CREATE TABLE

image.png

3.2 – 步骤2:创建存储过程(修正版):
ecommerce_db=# CREATE OR REPLACE PROCEDURE generate_order_summary() ecommerce_db-# LANGUAGE plmysql ecommerce_db-# AS $$ ecommerce_db$# BEGIN ecommerce_db$# DELETE FROM order_status_summary WHERE summary_date = CURRENT_DATE; ecommerce_db$# INSERT INTO order_status_summary (summary_date, status, order_count) ecommerce_db$# SELECT CURRENT_DATE, status, COUNT(*) ecommerce_db$# FROM orders ecommerce_db$# GROUP BY status; ecommerce_db$# END; ecommerce_db$# $$; CREATE PROCEDURE

image.png

4. 存储过程语法结构

4.1 – 无参数的存储过程示例:
ecommerce_db=# CREATE OR REPLACE PROCEDURE generate_order_summary() ecommerce_db-# LANGUAGE plmysql ecommerce_db-# AS $$ ecommerce_db$# BEGIN ecommerce_db$# DELETE FROM order_status_summary WHERE summary_date = CURRENT_DATE; ecommerce_db$# INSERT INTO order_status_summary (summary_date, status, order_count) ecommerce_db$# SELECT CURRENT_DATE, status, COUNT(*) FROM orders GROUP BY status; ecommerce_db$# END; ecommerce_db$# $$; CREATE PROCEDURE

image.png

金仓数据库对MySQL事件调度器的兼容性非常好,但语法细节需要精确匹配。这种"事件调用存储过程"的模式在实际业务中非常实用,特别适合报表生成、数据清理等定时任务场景。

4.2 – 检查事件调度器状态(金仓兼容PostgreSQL风格查询):
ecommerce_db=# SELECT name, setting ecommerce_db-# FROM sys_config ecommerce_db-# WHERE name = 'event_scheduler'; name | setting ------+--------- (0 rows)

image.png

4.3 – 或手动触发事件关联的存储过程(验证逻辑):
ecommerce_db=# CALL generate_order_summary(); CALL

image.png

4.4 – 查看执行结果:
ecommerce_db=# SELECT * FROM order_status_summary; summary_id | summary_date | status | order_count ------------+--------------+------------+------------- 1 | 2025-08-22 | PROCESSING | 3 2 | 2025-08-22 | COMPLETED | 1 (2 rows)

image.png

5、 创建该存储过程

(包含状态更新、审计日志记录及用户变量@old_status的使用):

5.1 – 步骤1:创建必要的表

– 订单表(假设结构,若已存在可跳过)

ecommerce_db=# CREATE TABLE IF NOT EXISTS orders ( ecommerce_db(# order_id INT PRIMARY KEY, ecommerce_db(# status VARCHAR(20) NOT NULL, ecommerce_db(# created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ecommerce_db(# ); NOTICE: relation "orders" already exists, skipping CREATE TABLE

image.png

5.2 – 审计日志表(记录状态变更):
ecommerce_db=# CREATE TABLE IF NOT EXISTS audit_log ( ecommerce_db(# log_id SERIAL PRIMARY KEY, ecommerce_db(# action VARCHAR(20) NOT NULL, ecommerce_db(# target_table VARCHAR(50) NOT NULL, ecommerce_db(# target_id INT NOT NULL, ecommerce_db(# old_value VARCHAR(20), -- 旧状态 ecommerce_db(# new_value VARCHAR(20), -- 新状态 ecommerce_db(# action_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ecommerce_db(# performed_by VARCHAR(50) DEFAULT CURRENT_USER ecommerce_db(# ); NOTICE: relation "audit_log" already exists, skipping CREATE TABLE

image.png

5.3 – 步骤2:创建存储过程update_order_status
ecommerce_db=# CREATE OR REPLACE PROCEDURE update_order_status( ecommerce_db(# p_order_id INT, ecommerce_db(# p_new_status VARCHAR(20) ecommerce_db(# ) ecommerce_db-# LANGUAGE plmysql ecommerce_db-# AS $$ ecommerce_db$# BEGIN ecommerce_db$# -- 1. 查询旧状态并存储到用户变量@old_status ecommerce_db$# SELECT status INTO @old_status FROM orders WHERE order_id = p_order_id; ecommerce_db$# ecommerce_db$# -- 2. 更新订单状态 ecommerce_db$# UPDATE orders ecommerce_db$# SET status = p_new_status ecommerce_db$# WHERE order_id = p_order_id; ecommerce_db$# ecommerce_db$# -- 3. 记录审计日志(包含旧状态和新状态) ecommerce_db$# INSERT INTO audit_log ( ecommerce_db$# action, ecommerce_db$# target_table, ecommerce_db$# target_id, ecommerce_db$# old_value, ecommerce_db$# new_value ecommerce_db$# ) VALUES ( ecommerce_db$# 'Status_Change', ecommerce_db$# 'orders', ecommerce_db$# p_order_id, ecommerce_db$# @old_status, ecommerce_db$# p_new_status ecommerce_db$# ); ecommerce_db$# END; ecommerce_db$# $$; CREATE PROCEDURE

image.png

5.4 – 步骤3:初始化测试数据

插入测试订单(状态为’NEW’):

ecommerce_db=# INSERT INTO orders (order_id, status) VALUES (1, 'NEW') ON CONFLICT DO NOTHING; WARNING: null value in column "customer_id" violates not-null constraint WARNING: null value in column "total_amount" violates not-null constraint INSERT 0 0

image.png

关键说明

  1. 存储过程不存在的原因:之前未创建update_order_status,需按上述步骤定义,明确参数类型(p_order_id INTp_new_status VARCHAR(20))。
  2. 用户变量@old_status的使用:在PLMYSQL中,通过SELECT ... INTO @old_status将旧状态存入会话级变量,后续可直接查询。
  3. 审计日志设计:扩展了audit_log表,增加old_valuenew_value字段,更清晰记录状态变更轨迹。

执行后,审计日志会显示订单1的状态从NEW变为SHIPPING@old_status也会返回NEW,符合预期场景。

如果报错,audit_log表中不存在old_value字段,添加缺失字段

5.5 – 步骤1:修改audit_log表结构,添加缺失字段
-- 为audit_log表添加old_value和new_value字段 ecommerce_db=# ALTER TABLE audit_log ecommerce_db-# ADD COLUMN IF NOT EXISTS old_value VARCHAR(20), ecommerce_db-# ADD COLUMN IF NOT EXISTS new_value VARCHAR(20); ALTER TABLE

image.png

5.6 – 步骤2:重新调用存储过程更新订单状态
-- 再次调用存储过程(此时字段已存在,可正常插入日志) ecommerce_db=# CALL update_order_status(1, 'SHIPPING'); CALL

image.png

5.7 – 步骤3:验证结果

查看审计日志(应包含旧状态和新状态):

ecommerce_db=# SELECT log_id, target_id, old_value, new_value, action_time ecommerce_db-# FROM audit_log ecommerce_db-# WHERE action = 'Status_Change'; log_id | target_id | old_value | new_value | action_time --------+-----------+------------+-----------+--------------------- 2 | 1 | PROCESSING | SHIPPING | 2025-08-22 09:31:40 (1 row)
5.8 – 确认订单状态已更新:
ecommerce_db=# SELECT order_id, status FROM orders WHERE order_id = 1; order_id | status ----------+---------- 1 | SHIPPING (1 row)

image.png

5.9 – 查看用户变量@old_status(记录旧状态):
ecommerce_db=# SELECT @old_status; @old_status ------------- PROCESSING (1 row)

image.png

关键原因分析

  • 最初创建的audit_log表可能缺少old_valuenew_value字段(与当前存储过程的插入逻辑不匹配),导致插入日志时触发“字段不存在”的错误。
  • 通过ALTER TABLE添加字段后,存储过程中的INSERT语句即可正常执行,审计日志能完整记录状态变更轨迹。

执行上述步骤后,订单状态会从PROCESSING更新为SHIPPING,审计日志会清晰记录这一变更,@old_status也会正确返回更新前的状态。

5.10 – 检查审计日志和变量:
ecommerce_db=# SELECT * FROM audit_log WHERE action = 'Status_Change'; log_id | action | target_table | target_id | action_time | performed_by | old_value | new_value --------+---------------+--------------+-----------+---------------------+--------------+------------+----------- 2 | Status_Change | orders | 1 | 2025-08-22 09:31:40 | system | PROCESSING | SHIPPING (1 row)

image.png

结果与分析: 存储过程 update_order_status 成功创建并执行。关键点在于:

  1. 存储过程使用 LANGUAGE plmysql 声明,表明使用兼容 MySQL 的存储过程语言。
  2. 在存储过程内部,通过 SELECT ... INTO @old_status 将查询结果赋值给用户变量 @old_status
  3. 在后续的 INSERT INTO audit_log 语句后,我们仍然可以在同一个会话中查询到 @old_status 的值,它保存了订单更新前的状态。这完美展示了用户变量在 PLMYSQL 存储过程内部和外部(同一会话)的可用性,极大地增强了脚本编写的灵活性。金仓对 PLMYSQL 中用户变量的支持非常到位。

(二) 事件调度器 (Event Scheduler) 兼容性测试

测试场景 2:创建定时事件 - 定期生成订单状态摘要 (使用 PLMYSQL 存储过程)

更复杂的任务通常会封装在存储过程中。

2.1 这里演示事件调用 PLMYSQL 存储过程。
ecommerce_db=# CREATE OR REPLACE PROCEDURE generate_order_summary() ecommerce_db-# LANGUAGE plmysql ecommerce_db-# AS $$ ecommerce_db$# BEGIN ecommerce_db$# -- 创建一个临时表或永久表存储摘要 (这里假设有个 summary_table) ecommerce_db$# -- 简化逻辑:将不同状态的订单计数插入摘要表 ecommerce_db$# INSERT INTO order_status_summary (summary_date, status, order_count) ecommerce_db$# SELECT CURRENT_DATE, status, COUNT(*) ecommerce_db$# FROM orders ecommerce_db$# GROUP BY status; ecommerce_db$# END; ecommerce_db$# $$; CREATE PROCEDURE

image.png

2.2 步骤 2:创建存储过程(兼容 PL/pgSQL):
ecommerce_db=# CREATE OR REPLACE PROCEDURE generate_order_summary() ecommerce_db-# LANGUAGE plpgsql -- 使用 PostgreSQL 原生过程语言 ecommerce_db-# AS $$ ecommerce_db$# BEGIN ecommerce_db$# -- 清空旧数据(假设需要保留历史) ecommerce_db$# DELETE FROM order_status_summary WHERE summary_date = CURRENT_DATE; ecommerce_db$# ecommerce_db$# -- 插入新摘要 ecommerce_db$# INSERT INTO order_status_summary (summary_date, status, order_count) ecommerce_db$# SELECT CURRENT_DATE, status, COUNT(*) ecommerce_db$# FROM orders ecommerce_db$# GROUP BY status; ecommerce_db$# END; ecommerce_db$# $$; CREATE PROCEDURE

image.png

2.2 验证操作,手动测试存储过程:
ecommerce_db=# SELECT * FROM order_status_summary; summary_id | summary_date | status | order_count ------------+--------------+------------+------------- 3 | 2025-08-22 | PROCESSING | 2 4 | 2025-08-22 | SHIPPING | 1 5 | 2025-08-22 | COMPLETED | 1 (3 rows)

image.png

3. 性能优化建议

3.1 启用 SQL 执行统计
ecommerce_db=# ALTER SYSTEM SET shared_preload_libraries = 'sys_stat_statements'; ALTER SYSTEM ecommerce_db=# SELECT pg_reload_conf(); pg_reload_conf ---------------- t (1 row)

image.png

3.2 使用 KingbaseES 自带的性能分析工具

查看当前活跃会话:

ecommerce_db=# SELECT * FROM sys_stat_activity; datid | datname | pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | xact_start | query_start | state_change | wait_event_type | wait_event | state | backend_xid | backend_xmin | query | backend_type -------+--------------+------+----------+---------+---------------------+-------------+-----------------+-------------+----------------------------+----------------------------+----------------------------+----------------------------+-----------------+---------------------+--------+-------------+--------------+----------------------------------+------------------------------ | | 2211 | | | auto vacuum | | | | 2025-08-20 15:44:20.791964 | | | | Activity | AutoVacuumMain | | | | | autovacuum launcher 12819 | kingbase | 2215 | 10 | system | ksh writer | | | | 2025-08-20 15:44:20.793866 | | | 2025-08-22 10:19:00.677327 | Activity | KshMain | idle | | | | ksh writer | | 2217 | 10 | system | sys_ksh collector | | | | 2025-08-20 15:44:20.794533 | | | 2025-08-22 10:19:01.001699 | Activity | KshMain | idle | | | | ksh collector | | 2218 | 10 | system | logical replication | | | | 2025-08-20 15:44:20.795272 | | | | Activity | LogicalLauncherMain | | | | | logical replication launcher 16465 | ecommerce_db | 8763 | 10 | system | ksql | | | -1 | 2025-08-22 09:11:51.448657 | 2025-08-22 10:19:01.433124 | 2025-08-22 10:19:01.433124 | 2025-08-22 10:19:01.433126 | | | active | | 944 | SELECT * FROM sys_stat_activity; | client backend | | 2209 | | | background flush | | | | 2025-08-20 15:44:20.791115 | | | | Activity | BgWriterMain | | | | | background writer | | 2208 | | | check pointer | | | | 2025-08-20 15:44:20.790813 | | | | Activity | CheckpointerMain | | | | | checkpointer | | 2210 | | | wal flush | | | | 2025-08-20 15:44:20.791647 | | | | Activity | WalWriterMain | | | | | walwriter (8 rows)

image.png

3.3 查看锁等待情况:

KingbaseES 通过 pg_locks 和 pg_stat_activity 系统视图提供锁信息:

查看当前所有锁及持有者:

ecommerce_db=# SELECT
ecommerce_db-#   pg_stat_activity.pid AS 进程ID,
ecommerce_db-#   pg_stat_activity.query AS 执行语句,
ecommerce_db-#   pg_locks.mode AS 锁模式,
ecommerce_db-#   pg_locks.granted AS 是否已获得锁
ecommerce_db-# FROM
ecommerce_db-#   pg_stat_activity
ecommerce_db-# JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid
ecommerce_db-# WHERE
ecommerce_db-#   pg_stat_activity.state = 'active';
 进程ID |                       执行语句                       |     锁模式      | 是否已获得锁 
--------+------------------------------------------------------+-----------------+--------------
   8763 | SELECT                                              +| AccessShareLock | t
        |   pg_stat_activity.pid AS 进程ID,                   +|                 | 
        |   pg_stat_activity.query AS 执行语句,               +|                 | 
        |   pg_locks.mode AS 锁模式,                          +|                 | 
        |   pg_locks.granted AS 是否已获得锁                  +|                 | 
        | FROM                                                +|                 | 
        |   pg_stat_activity                                  +|                 | 
        | JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid+|                 | 
        | WHERE                                               +|                 | 
        |   pg_stat_activity.state = 'active';                 |                 | 
   8763 | SELECT                                              +| AccessShareLock | t
        |   pg_stat_activity.pid AS 进程ID,                   +|                 | 
        |   pg_stat_activity.query AS 执行语句,               +|                 | 
        |   pg_locks.mode AS 锁模式,                          +|                 | 
        |   pg_locks.granted AS 是否已获得锁                  +|                 | 
        | FROM                                                +|                 | 
        |   pg_stat_activity                                  +|                 | 
        | JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid+|                 | 
        | WHERE                                               +|                 | 
        |   pg_stat_activity.state = 'active';                 |                 | 
   8763 | SELECT                                              +| ExclusiveLock   | t
        |   pg_stat_activity.pid AS 进程ID,                   +|                 | 
        |   pg_stat_activity.query AS 执行语句,               +|                 | 
        |   pg_locks.mode AS 锁模式,                          +|                 | 
        |   pg_locks.granted AS 是否已获得锁                  +|                 | 
        | FROM                                                +|                 | 
        |   pg_stat_activity                                  +|                 | 
        | JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid+|                 | 
        | WHERE                                               +|                 | 
        |   pg_stat_activity.state = 'active';                 |                 | 
   8763 | SELECT                                              +| AccessShareLock | t
        |   pg_stat_activity.pid AS 进程ID,                   +|                 | 
        |   pg_stat_activity.query AS 执行语句,               +|                 | 
        |   pg_locks.mode AS 锁模式,                          +|                 | 
        |   pg_locks.granted AS 是否已获得锁                  +|                 | 
        | FROM                                                +|                 | 
        |   pg_stat_activity                                  +|                 | 
        | JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid+|                 | 
        | WHERE                                               +|                 | 
        |   pg_stat_activity.state = 'active';                 |                 | 
   8763 | SELECT                                              +| AccessShareLock | t
        |   pg_stat_activity.pid AS 进程ID,                   +|                 | 
        |   pg_stat_activity.query AS 执行语句,               +|                 | 
        |   pg_locks.mode AS 锁模式,                          +|                 | 
        |   pg_locks.granted AS 是否已获得锁                  +|                 | 
        | FROM                                                +|                 | 
        |   pg_stat_activity                                  +|                 | 
        | JOIN pg_locks ON pg_locks.pid = pg_stat_activity.pid+|                 | 
        | WHERE                                               +|

五、 总结与体验官洞见

经过本次从创建库表到核心特性深度测试的完整旅程,金仓数据库 KingbaseES V9 在 MySQL 兼容性,特别是 PLMYSQL 兼容方面的表现给我留下了极其深刻的印象:

  1. 基础兼容扎实可靠: 库、表、索引的创建,数据的增删改查(CRUD),常用数据类型(SERIAL/AUTO_INCREMENT, TIMESTAMP, VARCHAR, DECIMAL)和函数(CURRENT_TIMESTAMP, ROW_COUNT(), CURRENT_USER)等基础 SQL 和 DDL 语法兼容性优异,迁移基础业务逻辑顺畅无阻。
  2. 用户变量 (@varname) 完美兼容: 赋值、在各类SQL语句中的使用、以及跨语句和在PLMYSQL存储过程中的传递和持久化,其行为与MySQL完全一致,是实现复杂业务逻辑的利器。
  3. 事件调度器 (Event Scheduler) 高度可用: 从事件的定义、调度配置(EVERY, STARTS)、到直接执行SQL或调用PLMYSQL存储过程,再到事件的管理和状态查看,整个流程成熟可靠,为自动化定时任务提供了坚实支撑。
  4. “平替”实力彰显,远超预期: 本次测试的用户变量和事件调度器,是MySQL应用中非常常见且关键的高级特性。金仓对这些特性的成熟、深度兼容,极大地消除了技术迁移的壁垒。它证明了“数据库平替用金仓”并非一句口号,而是在享受国产化、安全可控优势的同时,能够最大程度地保护用户的现有技术投资和开发习惯,真正做到了平滑、安心替代。

成为金仓产品体验官的收获远超预期: 这次深度体验不仅是一次技术验证,更是一次对国产数据库强大实力的见证。金仓团队对产品细节的打磨、对兼容性的高度重视以及对开发者体验的关注,都令人印象深刻。这种开放、透明的体验官计划,让我们能深入核心,与开发者共同成长,助力国产数据库生态走向繁荣。

#数据库平替用金仓 #金仓产品体验官

本文为金仓数据库产品体验官原创体验报告,实测环境基于KingbaseES V9,体验内容聚焦MySQL兼容特性。文中涉及的具体语法、功能及系统视图名称请以您使用的金仓数据库官方文档为准。

——以上仅为个人思考与建议,不代表行业普适观点。文中案例与思路仅供参考,若与实际情况巧合,纯属无意。期待与各位从业者共同探讨更多可能!

image.png

扫码关注我们【顺华星辰运维栈】了解更多信息

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论