一、写在前面
做 DBA 这么多年,GUI 工具我用过不少,KStudio、Navicat、DBeaver 都挺好使。但真正到了生产环境------尤其是那种只能通过堡垒机跳进去的机房服务器------你会发现,能依赖的只有命令行。KingbaseES 自带的 ksql 就是这样一个趁手的命令行工具,功能丰富且针对国产环境做了不少优化。这篇文章把我日常工作中最常用的 ksql 操作整理出来,希望能帮你少踩几个坑。
二、连接数据库:别小看这一行命令
2.1 找到你的 ksql
KingbaseES 安装后,ksql 一般藏在两个地方:
bash
# 服务端自带的
/opt/Kingbase/ES/V8/Server/bin/ksql
# 独立的客户端工具(推荐用这个)
/opt/Kingbase/ES/V8/ClientTools/bin/ksql
生产环境建议用 ClientTools 目录下的版本,不依赖服务端的库文件,拷贝到跳板机上也能直接用。如果你懒得记路径,直接加到环境变量:
bash
echo 'export PATH=/opt/Kingbase/ES/V8/ClientTools/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
2.2 基础连接方式
最朴素的连接命令长这样:
bash
ksql -U system -d test
-U 指定用户名,-d 指定数据库名。执行后会让你输密码,连上之后提示符变成这样:
bash
ksql (V8.0)
Type "help" for help.
test=#
注意那个 #,它表示当前用户是超级用户。如果是普通用户,提示符会变成 =>,这个细节在写操作文档时很有用,一眼就能看出来权限级别。
2.3 远程连接与密码处理
本地 socket 连接有个坑:有时候不指定 -h 参数,KingbaseES 不会强制验密,输什么密码都能进。这在开发环境是方便,生产环境就是安全隐患了。稳妥的做法是始终指定主机地址:
bash
ksql -U system -h 192.168.1.100 -p 54321 -W -d test
-W 是强制要求输入密码,-p 指定端口(金仓默认 54321,注意别跟其他数据库的默认端口搞混)。
如果你经常连同一个库,可以建一个密码文件免掉每次输入的麻烦:
bash
# ~/.pgpass 文件,权限必须是 600
chmod 600 ~/.pgpass
cat ~/.pgpass
内容格式:主机名:端口:数据库名:用户名:密码,比如:
ruby
192.168.1.100:54321:test:system:YourPassword123
2.4 环境变量偷懒法
如果你连的参数每次都一样,可以设几个环境变量:
ini
export KINGBASE_HOST=192.168.1.100
export KINGBASE_PORT=54321
export KINGBASE_DATABASE=test
export KINGBASE_USER=system
设完之后,直接敲 ksql 就能连,连 -U、-d 都不用写了。
三、交互模式:ksql 的核心战场
3.1 先搞清楚自己在哪
连进去之后,第一件事是确认环境,免得操作错了库:
sql
-- 当前连接信息
\conninfo
-- 数据库版本
SELECT version();
-- 许可证剩余天数(这个很重要,别等到过期了才发现)
SELECT get_license_validdays();
\conninfo 的输出大概长这样:
vbnet
You are connected to database "test" as user "system" on host "192.168.1.100" at port "54321".
3.2 数据库和对象的"地图"
在陌生的库里干活,就像进了一个没开灯的仓库,得先摸清布局。ksql 提供了一堆以 `` 开头的元命令,我称之为"地图工具":
diff
-- 列出所有数据库
\l
-- 切换到另一个库
\c production_db
-- 列出当前库的所有模式(Schema)
\dn
-- 列出当前模式下的所有表
\dt
-- 列出所有索引
\di
-- 列出所有视图
\dv
-- 列出所有函数
\df
-- 查看某张表的结构
\d orders
-- 查看表的权限分配
\dp orders
-- 列出所有角色/用户
\du
这些命令支持模糊匹配,比如你想找所有以 user 开头的表:
css
\dt user*
输出会过滤出 user_info、user_log、user_permission 之类的表。
3.3 结果格式化:让输出更符合你的习惯
默认的输出是表格对齐模式,字段多了之后会变得很难看。ksql 提供了几种格式化切换:
sql
-- 扩展模式,每行一个字段,适合字段很多的宽表
\x
-- 再执行一次查询,看看效果
SELECT * FROM user_info WHERE user_id = 10001;
扩展模式的输出会变成这样:
css
-[ RECORD 1 ]--------+--------------------------
user_id | 10001
username | zhangsan
email | zhangsan@company.com
created_at | 2024-03-15 09:23:17
last_login | 2026-05-07 18:45:33
is_active | t
department | 技术研发部
phone | 13800138000
比挤在一行里清晰多了。想切回表格模式,再执行一次 \x 就行。
其他常用的格式控制:
lua
-- 只显示数据,不显示表头
\t
-- 切换 HTML 输出(有时候需要把查询结果贴到邮件里)
\H
-- 设置 CSV 格式
\pset format csv
-- 设置字段分隔符为制表符(方便粘贴到 Excel)
\pset fieldsep '\t'
-- 显示执行时间
\timing on
\timing on 是我必开的选项,优化 SQL 的时候心里得有个数:
sql
\timing on
SELECT COUNT(*) FROM orders WHERE created_at > '2026-01-01';
输出末尾会多一行:
yaml
Time: 1243.567 ms (00:01.244)
3.4 把结果存到文件
有时候查询结果太多,终端里翻不动,或者需要交给别人分析,可以重定向到文件:
sql
-- 开始输出到文件
\o /tmp/query_result.txt
-- 执行查询
SELECT * FROM orders WHERE status = 'pending';
-- 关闭文件输出,回到终端
\o
更省事的做法是在 shell 层面直接重定向:
bash
ksql -U system -d test -c "SELECT * FROM orders" -o /tmp/orders.csv
四、脚本执行:从手工到自动化
4.1 执行外部 SQL 文件
这是最常用的场景。假设你有一个 init_tables.sql 文件:
bash
ksql -U system -d test -f init_tables.sql
如果想在交互模式里临时执行一个脚本:
arduino
\i /home/kingbase/scripts/backup_check.sql
4.2 单行命令快速执行
不需要进交互模式,直接在 shell 里执行一条 SQL:
bash
ksql -U system -d test -c "SELECT COUNT(*) FROM users"
输出:
markdown
count
-------
15234
(1 row)
这个技巧在写 Shell 脚本时特别好用,比如做一个定时巡检:
bash
#!/bin/bash
# daily_check.sh
DB_NAME="production"
USER="monitor"
# 检查连接数
CONN_COUNT=$(ksql -U $USER -d $DB_NAME -t -c "SELECT COUNT(*) FROM sys_stat_activity WHERE datname = '$DB_NAME'" | xargs)
if [ "$CONN_COUNT" -gt 400 ]; then
echo "[WARNING] $(date) - 当前连接数: $CONN_COUNT,接近上限" >> /var/log/db_check.log
fi
4.3 变量与条件执行
ksql 支持变量定义,这在写可复用的脚本时很有用:
sql
-- 定义变量
\set table_name 'orders'
\set start_date '2026-01-01'
-- 在 SQL 中使用变量
SELECT COUNT(*) FROM :table_name WHERE created_at > :'start_date';
注意语法细节::table_name 用于标识符(表名、列名),:'start_date' 用于字符串值。混用会报错,我第一次用的时候在这里卡了十分钟。
条件执行适合处理不同环境的差异化逻辑:
bash
\if :DB_NAME = 'production'
\echo '正在操作生产库,请谨慎!'
\elif :DB_NAME = 'test'
\echo '测试环境,放心折腾'
\else
\echo '未知环境'
\endif
4.4 错误处理:别让小错误搞崩整个脚本
默认情况下,ksql 遇到错误会继续往下执行,这在批处理脚本里很危险。建议开启严格模式:
ini
ksql -U system -d test -v ON_ERROR_STOP=1 -f critical_update.sql
或者在脚本开头加:
csharp
\set ON_ERROR_STOP on
这样一旦某条 SQL 失败,整个脚本会立刻退出,不会继续执行后面的语句,避免数据处于半完成状态。
五、一些不太起眼但很实用的高级技巧
5.1 历史命令与快速编辑
ksql 支持 Readline 库,上下箭头可以翻历史命令,Ctrl+R 可以反向搜索。更爽的是 \e 命令:
diff
-- 用外部编辑器编辑上一条命令
\e
这会调用你系统默认的编辑器(通常是 vi 或 nano),编辑完保存退出后,ksql 会自动执行修改后的命令。写复杂 SQL 的时候比在原终端里来回删改舒服多了。
5.2 在 ksql 里执行系统命令
不需要退出 ksql 就能看系统信息:
bash
-- 查看当前目录文件
! ls -lh
-- 查看磁盘空间(数据目录够不够?)
! df -h /opt/Kingbase/ES/V8/data
-- 切换工作目录
\cd /tmp
-- 查看当前工作目录
! pwd
这个 ! 命令我经常用来检查日志文件大小,或者临时拷贝备份文件。
5.3 大对象(LOB)操作
虽然现在的业务系统很少直接操作大对象了,但万一遇到老系统维护,这几个命令能救命:
lua
-- 导入文件到大对象
\lo_import '/tmp/product_manual.pdf'
-- 查看所有大对象
\lo_list
-- 导出大对象到文件
\lo_export 12345 '/tmp/exported_manual.pdf'
-- 删除大对象
\lo_unlink 12345
5.4 自定义提示符
默认的 test=# 太单调了,可以改成更有信息量的样式:
arduino
\set PROMPT1 '%n@%m %/%R%# '
效果:
perl
system@dbserver production=#
%n 是用户名,%m 是主机名(截断域名),%/ 是当前数据库名,%R 是提示符符号,%# 是超级用户标识。如果你管理多个环境,强烈建议把环境信息加到提示符里,避免误操作。
更花哨一点的,带颜色:
ini
\set PROMPT1 '%[%033[1;32m%]%n@%m%[%033[0m%] %/%R%# '
这样用户名和主机名是绿色的,在黑白终端里一眼就能定位。
5.5 自动提交控制
KingbaseES 默认是自动提交模式,每条 SQL 执行完就提交。如果你需要显式控制事务:
sql
-- 关闭自动提交
\set AUTOCOMMIT off
-- 现在可以手动控制事务了
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- 确认没问题再提交
COMMIT;
-- 或者发现问题回滚
-- ROLLBACK;
关闭自动提交后,退出 ksql 时如果有未提交的事务,会收到警告,避免漏提交。
六、KingbaseES 特有功能
6.1 兼容模式查看
金仓的一个卖点是兼容 Oracle 和 MySQL,你可以查看当前的兼容模式:
ini
SHOW COMPATIBILITY_MODE;
返回值可能是 STD(标准模式)、ORA(Oracle 模式)或 MYSQL(MySQL 模式)。不同模式下,同样的 SQL 可能有不同的行为,迁移的时候尤其要注意。
6.2 查看已安装的扩展
\dx
输出示例:
sql
List of installed extensions
Name | Version | Schema | Description
-----------------+---------+------------+-----------------------------------------------------------
plsql | 1.0 | pg_catalog | PL/SQL procedural language
sys_stat_statements | 1.0 | public | track execution statistics of all SQL statements
pgcrypto | 1.3 | public | cryptographic functions
sys_stat_statements 是性能分析的利器,默认可能没有启用,需要手动加载:
sql
CREATE EXTENSION IF NOT EXISTS sys_stat_statements;
6.3 错误详情查看
SQL 报错时,默认信息有时候不够详细。用 \errverbose 可以看到更完整的信息:
vbnet
SELECT * FROM non_existent_table;
-- ERROR: relation "non_existent_table" does not exist
\errverbose
输出会包含 SQLSTATE 错误码、出错位置等详细信息,排错的时候很有用。
七、常见问题与排错
7.1 连接失败排查 checklist
遇到连不上的情况,按这个顺序检查:
-
服务有没有起
perlps -ef | grep kingbase -
端口对不对?
perlss -tlnp | grep 54321 -
监听地址设了没? 检查
kingbase.conf里的listen_addresses,默认可能是localhost,远程连需要改成'*'或具体 IP。 -
防火墙放行了吗
cssfirewall-cmd --list-ports -
密码对不对? 注意 KingbaseES 的密码策略,默认可能有复杂度要求,而且区分大小写。
7.2 字符集乱码
遇到中文乱码,先查编码:
sql
-- 服务端编码
SHOW server_encoding;
-- 客户端编码
SHOW client_encoding;
-- 修改客户端编码
\encoding UTF8
如果服务端是 UTF8,客户端是 GBK,中文基本会乱。统一成 UTF8 最省事。
7.3 权限问题
报错 permission denied for relation,先确认权限:
sql
-- 查看当前用户
SELECT current_user;
-- 查看表权限
\dp table_name
-- 查看角色权限
\du username
有时候不是没权限,是搜索路径(search_path)不对,表在别的 Schema 里:
sql
-- 查看当前搜索路径
SHOW search_path;
-- 临时切换
SET search_path TO app_schema, public;
八、实用命令速查表
最后整理一张速查表,建议收藏或者打印贴显示器旁边:
| 命令 | 作用 |
|---|---|
\l |
列出所有数据库 |
\c dbname |
切换数据库 |
\dt |
列出当前模式下的表 |
\d tablename |
查看表结构 |
\di |
列出索引 |
\dv |
列出视图 |
\df |
列出函数 |
\dn |
列出模式 |
\du |
列出角色/用户 |
\dp |
列出权限 |
\x |
切换扩展显示模式 |
\t |
切换只显示数据(无表头) |
\timing on/off |
开启/关闭执行时间显示 |
\o filename |
输出结果到文件 |
\i filename |
执行外部 SQL 文件 |
\e |
用编辑器编辑上条命令 |
! command |
执行系统命令 |
\cd dir |
切换工作目录 |
\conninfo |
显示当前连接信息 |
\q |
退出 ksql |
? |
查看所有元命令帮助 |
\h SQL命令 |
查看 SQL 语法帮助 |
九、写在最后
ksql 这个工具,表面上看起来就是个黑框框,但用熟了之后效率比 GUI 高得多。特别是当你需要批量处理、写自动化脚本、或者在服务器直接排错的时候,命令行的优势是图形工具没法比的。
几个我个人觉得最值得养成习惯的操作:
- 连接时始终加
-h参数,养成安全连接的习惯; - 开
\timing on,对 SQL 性能心里有数; - 复杂操作先
\set AUTOCOMMIT off,给自己留回滚的余地; - 用好
\o和-f,把重复操作脚本化。
如果你是从 MySQL 的 mysql 客户端转过来的,刚开始可能会觉得 ksql 的元命令语法有点别扭(为啥都是反斜线?),但坚持用一周,基本就能形成肌肉记忆了。毕竟,命令行工具的设计逻辑一旦熟悉,效率提升是非常明显的。
如果这篇文章对你有帮助,点个赞或者收藏一下,下次找起来方便。有问题也可以留言,看到都会回。