KingbaseES數(shù)據(jù)庫開發(fā)運(yùn)維:部署、安全、備份與監(jiān)控實(shí)戰(zhàn)
寫在開頭
干數(shù)據(jù)庫這行有些年頭了,從最早用商業(yè)庫到后來折騰各種國產(chǎn)庫,踩過的坑說多了都是淚。這兩年信創(chuàng)項(xiàng)目越來越多,KES 數(shù)據(jù)庫在政企、金融、能源領(lǐng)域鋪得挺廣,身邊不少朋友開始接觸它。說實(shí)話,剛上手的時(shí)候我也摸不著頭腦——文檔雖然有,但很多細(xì)節(jié)得靠自己踩坑才能搞明白。有些配置參數(shù)改了之后要重啟才生效,有些不用;有些功能要裝擴(kuò)展才能用,有些默認(rèn)就開著。這些東西文檔里都有寫,但散落在各個(gè)章節(jié)里,找起來費(fèi)勁。
這篇文章算是一個(gè)階段性的總結(jié),把部署配置、安全管理、備份恢復(fù)、日常監(jiān)控這幾個(gè)方面的心得記下來。適合有一定數(shù)據(jù)庫基礎(chǔ)、剛開始接觸 KingbaseES 的開發(fā)和運(yùn)維人員。內(nèi)容偏實(shí)操,理論部分點(diǎn)到為止,重點(diǎn)還是那些命令和配置。如果你是正在做信創(chuàng)項(xiàng)目選型或者剛接手一個(gè) KES 數(shù)據(jù)庫的運(yùn)維工作,這篇文章應(yīng)該能幫你少走一些彎路。
安裝部署與環(huán)境初始化
裝庫這事本身不難,但有些細(xì)節(jié)不注意后面會吃苦頭。KES 支持主流國產(chǎn)操作系統(tǒng),麒麟、統(tǒng)信、中科方德都沒問題,x86 和 ARM 架構(gòu)也都能跑。我一般在 CentOS 和麒麟 V10 上裝得比較多,流程差不多。有一點(diǎn)要提前確認(rèn):操作系統(tǒng)的內(nèi)核參數(shù)和網(wǎng)絡(luò)配置要符合數(shù)據(jù)庫的安裝要求,特別是大頁內(nèi)存(hugepages)的設(shè)置,生產(chǎn)環(huán)境下開啟大頁對性能有幫助。
安裝包獲取與準(zhǔn)備
安裝介質(zhì)從電科金倉官方渠道獲取,一般是 ISO 或者 tar.gz 格式。拿到之后先校驗(yàn)一下 MD5,別因?yàn)橄螺d不完整浪費(fèi)時(shí)間。解壓之后目錄結(jié)構(gòu)大致是這樣的:
tar -xzf KingbaseES_V9_xxx.tar.gz cd KingbaseES_V9_xxx # 看一下目錄結(jié)構(gòu) ls -l # setup.sh 是安裝腳本 # license.dat 是授權(quán)文件,沒這個(gè)裝不了
裝之前確認(rèn)系統(tǒng)用戶和環(huán)境變量。建議用專門的 kingbase 用戶來安裝和運(yùn)行數(shù)據(jù)庫服務(wù),別用 root。
# 創(chuàng)建專用用戶 useradd -m kingbase passwd kingbase # 設(shè)置目錄權(quán)限 chown -R kingbase:kingbase /opt/Kingbase
執(zhí)行安裝
KES 提供圖形界面安裝和靜默安裝兩種方式。服務(wù)器環(huán)境下我推薦用靜默安裝,快且不容易出錯(cuò)。圖形界面那個(gè)在遠(yuǎn)程終端里跑起來卡得很,沒必要。
# 靜默安裝示例 ./setup.sh -i console \ -d /opt/Kingbase/ES/V9 \ -p server \ -U system \ -W "YourPassword123" \ --license /opt/license.dat
安裝過程中會讓你選擇兼容模式,這個(gè)比較關(guān)鍵。KingbaseES 支持 Oracle 兼容、MySQL 兼容和標(biāo)準(zhǔn)模式三種。選哪種取決于你的業(yè)務(wù)原來用的是什么庫。如果是新開發(fā)的項(xiàng)目,標(biāo)準(zhǔn)模式就挺好,SQL 行為最規(guī)范;如果是從 Oracle 遷過來的,選 Oracle 兼容模式會省很多事,存儲過程、包、自定義類型基本上不用怎么改就能跑。MySQL 兼容模式同理,對 MySQL 的方言和函數(shù)做了適配。不過要注意,兼容模式選定之后不能隨便切換,建議在項(xiàng)目初期就確定好。
初始化與啟動
裝完之后初始化數(shù)據(jù)庫實(shí)例,這個(gè)過程跟其他關(guān)系型數(shù)據(jù)庫類似:
# 切到 kingbase 用戶 su - kingbase # 初始化數(shù)據(jù)目錄 initdb -D /data/kingbase/data \ -U system \ -W \ --encoding=UTF8 \ --locale=zh_CN.UTF-8 # 啟動服務(wù) sys_ctl -D /data/kingbase/data start # 確認(rèn)服務(wù)狀態(tài) sys_ctl -D /data/kingbase/data status
啟動之后第一件事是改默認(rèn)密碼和配置 ksql 的訪問權(quán)限。ksql 是 KES 自帶的命令行交互工具,跟其他數(shù)據(jù)庫的 CLI 工具用法差不多,SQL 語句直接敲進(jìn)去就能執(zhí)行。
-- 通過 ksql 連接 -- ksql -U system -d test -p 54321 -- 改掉默認(rèn)密碼 ALTER USER system WITH PASSWORD 'NewStrongP@ss2026'; -- 看一下當(dāng)前數(shù)據(jù)庫列表 SELECT datname, datowner, encoding FROM sys_database;
配置文件調(diào)整
初始化完成后的默認(rèn)配置只能跑跑測試,生產(chǎn)環(huán)境得改幾個(gè)關(guān)鍵參數(shù)。配置文件在數(shù)據(jù)目錄下的 kingbase.conf:
-- 這幾個(gè)參數(shù)改完需要重啟 shared_buffers = 4GB work_mem = 64MB maintenance_work_mem = 512MB effective_cache_size = 12GB -- 連接數(shù)根據(jù)實(shí)際并發(fā)來定 max_connections = 200 -- 日志相關(guān) logging_collector = on log_directory = 'sys_log' log_filename = 'kingbase-%Y-%m-%d.log' log_min_duration_statement = 1000 log_rotation_age = 1d
shared_buffers 一般設(shè)成物理內(nèi)存的 25% 左右,不要貪大。我有次設(shè)到 60% 結(jié)果系統(tǒng)緩存不夠用,IO 反而變高了。work_mem 注意它是每個(gè)排序操作各自分配的,并發(fā)高的話別設(shè)太猛,不然內(nèi)存會被吃光。
網(wǎng)絡(luò)訪問配置
默認(rèn)只允許本機(jī)連接,要讓其他機(jī)器訪問得改兩個(gè)地方。一個(gè)是 kingbase.conf 里的 listen_addresses,另一個(gè)是 sys_hba.conf 里的訪問控制規(guī)則:
# kingbase.conf listen_addresses = '*' port = 54321 # sys_hba.conf # 允許內(nèi)網(wǎng)段訪問 host all all 192.168.1.0/24 scram-sha-256
改完這兩個(gè)文件要 reload 一下配置,不用重啟:
sys_ctl -D /data/kingbase/data reload
sys_hba.conf 這個(gè)文件相當(dāng)于數(shù)據(jù)庫的防火墻規(guī)則,格式是"連接類型 數(shù)據(jù)庫 用戶 地址 認(rèn)證方式"。scram-sha-256 是目前推薦的密碼認(rèn)證方式,比老的 md5 更安全。如果涉及跨公網(wǎng)的訪問,建議走 SSL 連接,在 sys_hba.conf 里用 hostssl 代替 host,強(qiáng)制走加密通道。KES 默認(rèn)支持 SSL,只需要把證書和密鑰放到數(shù)據(jù)目錄下并在 kingbase.conf 里開啟 ssl = on 就行。
SQL 開發(fā)與日常操作
KES 的 SQL 語法對標(biāo)準(zhǔn) SQL 的支持很完整,日常開發(fā)用到的 DDL、DML、事務(wù)控制都沒什么問題。這部分不打算寫教科書式的內(nèi)容,重點(diǎn)記一些實(shí)際項(xiàng)目中容易忽略的點(diǎn)。
建表與數(shù)據(jù)類型選擇
建表的時(shí)候數(shù)據(jù)類型選擇挺有講究的。我見過不少項(xiàng)目清一色 VARCHAR + INT + TIMESTAMP,把數(shù)據(jù)庫當(dāng) Excel 用了。KES 支持的類型比大多數(shù)人用得到的要多不少。
CREATE TABLE device_info (
id BIGSERIAL PRIMARY KEY,
device_code VARCHAR(64) NOT NULL UNIQUE,
device_name VARCHAR(200) NOT NULL,
category SMALLINT DEFAULT 1,
specs JSONB,
tags TEXT[],
location POINT,
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now()
);
-- JSONB 類型特別適合存半結(jié)構(gòu)化的配置信息
INSERT INTO device_info (device_code, device_name, specs)
VALUES (
'DEV-20260101-001',
'溫濕度傳感器-A3',
'{"protocol": "MQTT", "interval": 30, "unit": "celsius"}'::jsonb
);
-- 查詢 JSONB 里的字段
SELECT device_code,
specs->>'protocol' AS protocol,
(specs->>'interval')::int AS report_interval
FROM device_info
WHERE specs ? 'protocol';
數(shù)組類型存標(biāo)簽、角色列表這類東西很方便,省得建額外的關(guān)聯(lián)表。JSONB 用來存配置項(xiàng)、擴(kuò)展屬性這種半結(jié)構(gòu)化數(shù)據(jù),比搞一堆 VARCHAR 列強(qiáng)多了。
事務(wù)與并發(fā)控制
KES 的事務(wù)管理跟標(biāo)準(zhǔn) SQL 一致,BEGIN / COMMIT / ROLLBACK 這套東西沒什么好說的。說一個(gè)實(shí)際遇到的問題。
有個(gè)項(xiàng)目上線后發(fā)現(xiàn)頻繁出現(xiàn)死鎖。排查下來是因?yàn)閮蓚€(gè)業(yè)務(wù)模塊同時(shí)更新同一批數(shù)據(jù),但更新順序不一樣——模塊 A 先更新訂單表再更新庫存表,模塊 B 反過來先更新庫存表再更新訂單表,并發(fā)一高就死鎖了。解決方法是保證所有涉及多行更新的業(yè)務(wù)邏輯按固定順序操作,開發(fā)團(tuán)隊(duì)約定了一個(gè)統(tǒng)一的表操作優(yōu)先級規(guī)范。
另外,KES 支持 NOWAIT 和 SKIP LOCKED 語法,在高并發(fā)搶鎖的場景下很有用:
-- 搶不到鎖就立即返回錯(cuò)誤,不傻等 SELECT * FROM task_queue WHERE status = 0 FOR UPDATE NOWAIT; -- 跳過已被其他事務(wù)鎖定的行,處理下一批 SELECT * FROM task_queue WHERE status = 0 FOR UPDATE SKIP LOCKED LIMIT 10;
SKIP LOCKED 特別適合做任務(wù)隊(duì)列這種場景,多個(gè)消費(fèi)者同時(shí)取任務(wù),各自拿到不重復(fù)的任務(wù)去處理,不會互相阻塞。之前有個(gè)項(xiàng)目用一張表做消息隊(duì)列,沒有 SKIP LOCKED 之前經(jīng)常因?yàn)殒i等待導(dǎo)致任務(wù)分發(fā)延遲,加上之后吞吐量直接翻了兩倍多。所以如果你的業(yè)務(wù)有類似的并發(fā)模型,這兩個(gè)語法一定要用起來。
批量操作性能
批量插入數(shù)據(jù)的時(shí)候別一條一條 INSERT,用 COPY 命令會快幾個(gè)數(shù)量級。這個(gè)經(jīng)驗(yàn)適用于大多數(shù)關(guān)系型數(shù)據(jù)庫。COPY 走的是二進(jìn)制協(xié)議,跳過了 SQL 解析和優(yōu)化的開銷,百萬級數(shù)據(jù)的導(dǎo)入通常在十幾秒內(nèi)就能完成:
-- 從 CSV 文件批量導(dǎo)入,速度比 INSERT 快得多
COPY device_info (device_code, device_name, category)
FROM '/data/import/devices.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ',');
-- 如果是程序里拼接批量 INSERT,至少用多值語法
INSERT INTO device_info (device_code, device_name, category)
VALUES
('DEV-001', '溫度傳感器', 1),
('DEV-002', '壓力傳感器', 2),
('DEV-003', '流量計(jì)', 3);
更新和刪除大量數(shù)據(jù)的時(shí)候也有講究。一次性 DELETE 幾千萬行會長時(shí)間持有大量鎖,影響線上業(yè)務(wù)。建議分批操作,每次處理一小批,中間讓出鎖:
-- 分批刪除過期數(shù)據(jù)
DO $$
DECLARE
batch_size INT := 5000;
deleted INT;
BEGIN
LOOP
DELETE FROM sensor_data
WHERE ctid IN (
SELECT ctid FROM sensor_data
WHERE record_time < '2024-01-01'
LIMIT batch_size
);
GET DIAGNOSTICS deleted = ROW_COUNT;
COMMIT;
EXIT WHEN deleted < batch_size;
-- 暫停一下,給其他事務(wù)讓路
PERFORM pg_sleep(0.5);
END LOOP;
END $$;
安全管理:三權(quán)分立與數(shù)據(jù)加密
安全這塊是 KES 比較強(qiáng)的地方,畢竟過了等保四級認(rèn)證的產(chǎn)品。很多政企項(xiàng)目對數(shù)據(jù)庫安全有硬性要求,不達(dá)標(biāo)驗(yàn)收都過不了。KingbaseES 在安全方面做了很多工作,從訪問控制到數(shù)據(jù)加密到審計(jì)追蹤,形成了一套比較完整的安全防護(hù)體系。
三權(quán)分立
KES 支持三權(quán)分立的安全管理模式,把數(shù)據(jù)庫管理權(quán)限拆分成三個(gè)角色:系統(tǒng)管理員(SYSSO)負(fù)責(zé)日常運(yùn)維和對象管理,安全管理員(SECO)負(fù)責(zé)安全策略和審計(jì)配置,審計(jì)管理員(AUDSO)負(fù)責(zé)審計(jì)日志的查看和管理。三個(gè)角色互相制約,任何一個(gè)人拿不到全部權(quán)限。
-- 啟用三權(quán)分立需要修改配置 -- kingbase.conf 中設(shè)置 -- enable_sec_admin = on -- 改完重啟生效 -- 查看當(dāng)前角色和權(quán)限分配 SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolcanlogin FROM sys_roles ORDER BY rolname;
三權(quán)分離這個(gè)設(shè)計(jì)思路其實(shí)跟企業(yè)管理里的"不相容職務(wù)分離"是一個(gè)道理。系統(tǒng)管理員能建表建用戶但看不到審計(jì)日志,審計(jì)管理員能看到所有人的操作記錄但改不了數(shù)據(jù)和配置,安全管理員管策略但碰不到業(yè)務(wù)數(shù)據(jù)。
用戶和權(quán)限管理
權(quán)限分配遵循最小化原則,別圖省事給普通應(yīng)用賬號 SUPERUSER 權(quán)限。我見過好幾個(gè)項(xiàng)目為了調(diào)試方便直接給 dba 權(quán)限上線的,后面審計(jì)的時(shí)候全被打了回來。
-- 創(chuàng)建只讀用戶 CREATE ROLE readonly_user WITH LOGIN PASSWORD 'Read@2026'; GRANT CONNECT ON DATABASE production TO readonly_user; GRANT USAGE ON SCHEMA public TO readonly_user; GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user; -- 設(shè)置默認(rèn)權(quán)限,以后新建的表也自動有 SELECT 權(quán)限 ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_user; -- 創(chuàng)建應(yīng)用用戶,只給增刪改查權(quán)限 CREATE ROLE app_user WITH LOGIN PASSWORD 'App@2026'; GRANT CONNECT ON DATABASE production TO app_user; GRANT USAGE, CREATE ON SCHEMA public TO app_user; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
透明數(shù)據(jù)加密 TDE
KES 支持透明數(shù)據(jù)加密,也就是 TDE。開啟之后數(shù)據(jù)在磁盤上是加密存儲的,讀寫的時(shí)候由數(shù)據(jù)庫引擎自動加解密,應(yīng)用層完全無感知。對于存儲敏感信息的場景,這個(gè)功能是剛需。
-- 創(chuàng)建加密表空間
CREATE TABLESPACE encrypted_ts
LOCATION '/data/kingbase/encrypted'
WITH (encrypt_type = 'SM4');
-- 在加密表空間上建表
CREATE TABLE user_identity (
id BIGSERIAL PRIMARY KEY,
user_name VARCHAR(100) NOT NULL,
id_card VARCHAR(18) NOT NULL,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT now()
) TABLESPACE encrypted_ts;
加密算法支持國密 SM4,也支持 AES。選型的時(shí)候根據(jù)合規(guī)要求來定,政務(wù)類項(xiàng)目一般要求國密算法。需要注意的是,加密表空間對性能有一定影響,大概在 5% 到 10% 左右,具體看數(shù)據(jù)量和讀寫比例。
審計(jì)配置
審計(jì)功能可以記錄指定用戶或指定操作的訪問日志,事后追溯誰在什么時(shí)間做了什么操作。開啟方式不復(fù)雜:
-- 通過安全管理員配置審計(jì)策略
-- 記錄所有 DDL 操作
SELECT audit_set_rule('audit_ddl', 'on');
-- 記錄對敏感表的訪問
SELECT audit_set_object('public.user_identity', 'select,insert,update,delete');
-- 查看審計(jì)日志
SELECT event_time, username, event_type, object_name, statement
FROM sys_audit_log
WHERE event_time > now() - INTERVAL '1 day'
ORDER BY event_time DESC
LIMIT 50;
審計(jì)日志量大的話記得定期歸檔和清理,別讓審計(jì)表把磁盤撐滿了。我就遇到過這種事,審計(jì)開了半年沒人管,某天磁盤報(bào)警才發(fā)現(xiàn)審計(jì)日志占了 200 多 G。
備份恢復(fù)與高可用
數(shù)據(jù)備份這事不用多說了,沒備份的數(shù)據(jù)庫就是在裸奔。KES 自帶的備份工具叫 sys_rman,功能跟 Oracle 的 RMAN 差不多,支持全量備份、增量備份和時(shí)間點(diǎn)恢復(fù)。
物理備份
# 全量備份 sys_rman -F /data/kingbase/backup backup full # 增量備份(基于上次全量或增量) sys_rman -F /data/kingbase/backup backup incremental # 查看備份集信息 sys_rman -F /data/kingbase/backup show # 清理過期備份(保留最近 7 天) sys_rman -F /data/kingbase/backup delete --older-than 7d
建議的備份策略是每周一次全量,每天一次增量,備份保留周期根據(jù)業(yè)務(wù)需要和磁盤空間來定。備份完了別忘了驗(yàn)證,sys_rman 支持 validate 命令:
# 驗(yàn)證備份完整性 sys_rman -F /data/kingbase/backup validate
不驗(yàn)證的備份跟沒有備份區(qū)別不大。之前有個(gè)客戶的數(shù)據(jù)庫硬盤壞了,拿備份出來恢復(fù)的時(shí)候才發(fā)現(xiàn)三個(gè)月前的某次備份文件就壞了,中間一直沒驗(yàn)證過。最后只能恢復(fù)到更早的時(shí)間點(diǎn),丟了不少數(shù)據(jù)。
時(shí)間點(diǎn)恢復(fù) PITR
誤刪數(shù)據(jù)是 DBA 的噩夢。KES 支持 PITR(Point-In-Time Recovery),可以把數(shù)據(jù)庫恢復(fù)到過去任意一個(gè)時(shí)間點(diǎn),前提是歸檔日志要完整。
# 恢復(fù)步驟概要 # 1. 停庫 sys_ctl -D /data/kingbase/data stop # 2. 恢復(fù)基礎(chǔ)備份 sys_rman -F /data/kingbase/backup restore --target-time "2026-06-04 15:30:00" # 3. 配置恢復(fù)目標(biāo) # 在 kingbase.auto.conf 中設(shè)置 # recovery_target_time = '2026-06-04 15:30:00' # recovery_target_action = 'promote' # 4. 啟動恢復(fù) sys_ctl -D /data/kingbase/data start
PITR 的前提是持續(xù)歸檔要正常。歸檔配置在 kingbase.conf 里:
archive_mode = on archive_command = 'cp %p /data/kingbase/archive/%f'
歸檔目錄別跟數(shù)據(jù)目錄放在同一塊盤上,盤壞了就全沒了。有條件的話用 NFS 或者對象存儲做歸檔目的地。
高可用集群
生產(chǎn)環(huán)境的 KES 一般部署成主備集群。主庫處理讀寫請求,備庫通過流復(fù)制實(shí)時(shí)同步數(shù)據(jù)。主庫掛了可以手動切換也可以自動切換。KES 自帶的高可用組件能實(shí)現(xiàn)自動故障檢測和切換,RTO 通??刂圃?30 秒以內(nèi)。
# 備庫搭建:基于主庫做基礎(chǔ)備份 sys_basebackup -h primary_host -p 54321 -U replication_user \ -D /data/kingbase/standby \ -Fp -Xs -P # 備庫配置 recovery 參數(shù) # kingbase.auto.conf primary_conninfo = 'host=primary_host port=54321 user=replication_user password=xxx' hot_standby = on
流復(fù)制有兩種模式:同步復(fù)制保證 RPO 為零,每條事務(wù)至少在備庫寫了一份 WAL 才算提交成功;異步復(fù)制性能更好但可能丟少量數(shù)據(jù)。關(guān)鍵業(yè)務(wù)用同步,非關(guān)鍵業(yè)務(wù)用異步,看具體取舍。
-- 查看復(fù)制狀態(tài)
SELECT pid, usename, application_name, client_addr,
state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM sys_stat_replication;
這里有個(gè)要注意的地方:同步復(fù)制對網(wǎng)絡(luò)延遲很敏感。如果主備之間網(wǎng)絡(luò)延遲超過 5 毫秒,寫入性能就會明顯下降??鐧C(jī)房部署的時(shí)候測一下延遲再決定用同步還是異步。
日常監(jiān)控與性能診斷
數(shù)據(jù)庫監(jiān)控做得好不好直接決定你能不能提前發(fā)現(xiàn)問題。等用戶打電話說"系統(tǒng)怎么這么慢"再去查,往往已經(jīng)晚了。我習(xí)慣把監(jiān)控分成三層:第一層是操作系統(tǒng)級別的,CPU、內(nèi)存、磁盤 IO、網(wǎng)絡(luò)帶寬;第二層是數(shù)據(jù)庫實(shí)例級別的,連接數(shù)、事務(wù)量、鎖等待、緩存命中率;第三層是 SQL 級別的,慢查詢、執(zhí)行計(jì)劃、索引使用情況。這篇文章重點(diǎn)說后兩層。
KWR 性能報(bào)告
KES 內(nèi)置了一個(gè)叫 KWR(Kingbase Workload Repository)的性能采集工具,功能跟 Oracle 的 AWR 報(bào)告很像。它會周期性地給數(shù)據(jù)庫拍快照,記錄各種性能指標(biāo)的累積值。對比兩個(gè)快照之間的差異就能看出這段時(shí)間數(shù)據(jù)庫的負(fù)載情況。
-- 確認(rèn) KWR 擴(kuò)展已安裝 CREATE EXTENSION IF NOT EXISTS sys_kwr; -- 手動創(chuàng)建一個(gè)快照 SELECT sys_kwr_snapshot(); -- 生成兩個(gè)快照之間的性能報(bào)告 -- 先查看快照 ID SELECT snap_id, snap_time FROM sys_kwr_snapshots ORDER BY snap_id DESC LIMIT 10; -- 生成報(bào)告(輸出到文件) \o /tmp/kwr_report.html SELECT sys_kwr_report(101, 105, 'html'); \o
KWR 報(bào)告里的信息量很大,我一般重點(diǎn)看幾個(gè)部分:等待事件排名、TOP SQL(按總耗時(shí)和調(diào)用次數(shù)排序)、緩存命中率、檢查點(diǎn)統(tǒng)計(jì)。如果某個(gè)等待事件突然飆升,基本就能定位到瓶頸在哪。
活躍會話分析
KSH(Kingbase Session History)記錄每個(gè)活躍會話在采樣時(shí)刻的等待事件和執(zhí)行信息,粒度比 KWR 更細(xì)。適合排查某個(gè)時(shí)間點(diǎn)的性能抖動。
-- 啟用 KSH CREATE EXTENSION IF NOT EXISTS sys_ksh; -- 查看最近 5 分鐘最耗時(shí)的等待事件 SELECT wait_event_type, wait_event, count(*) FROM sys_ksh WHERE sample_time > now() - INTERVAL '5 minutes' GROUP BY 1, 2 ORDER BY 3 DESC LIMIT 10; -- 查看某段時(shí)間內(nèi)執(zhí)行最慢的 SQL SELECT query_id, query, calls, total_time, mean_time FROM sys_ksh_statements WHERE sample_time > now() - INTERVAL '1 hour' ORDER BY mean_time DESC LIMIT 10;
實(shí)時(shí)會話與鎖監(jiān)控
日常巡檢的時(shí)候經(jīng)常要看當(dāng)前有沒有長時(shí)間運(yùn)行的事務(wù)、有沒有鎖等待。幾條常用查詢:
-- 當(dāng)前活躍會話
SELECT pid, usename, application_name, client_addr,
state, wait_event_type, wait_event,
now() - query_start AS duration, query
FROM sys_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
-- 鎖等待分析
SELECT blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query,
now() - blocked.query_start AS wait_duration
FROM sys_stat_activity blocked
JOIN sys_locks l ON blocked.pid = l.pid AND NOT l.granted
JOIN sys_locks granted ON l.locktype = granted.locktype
AND l.database IS NOT DISTINCT FROM granted.database
AND l.relation IS NOT DISTINCT FROM granted.relation
AND granted.granted = true
JOIN sys_stat_activity blocking ON granted.pid = blocking.pid
WHERE blocked.pid != blocking.pid;
-- 長時(shí)間未提交的事務(wù)(超過 5 分鐘)
SELECT pid, usename, now() - xact_start AS xact_duration, query
FROM sys_stat_activity
WHERE state = 'idle in transaction'
AND now() - xact_start > INTERVAL '5 minutes'
ORDER BY xact_duration DESC;
idle in transaction 這種狀態(tài)特別值得警惕。事務(wù)打開了但沒有提交,一直掛著,持有的鎖不釋放。如果掛太久,VACUUM 都沒法回收死元組,表會越來越大。建議在 kingbase.conf 里設(shè)個(gè)超時(shí):
idle_in_transaction_session_timeout = 300000 -- 5 分鐘,單位毫秒
磁盤和表空間監(jiān)控
寫個(gè)簡單的巡檢腳本定期跑一下,把表空間使用情況、大表列表、索引膨脹率這些都采集出來。不用搞得太復(fù)雜,shell 腳本加上 ksql 就夠用:
#!/bin/bash
# db_check.sh - 簡單巡檢腳本
DATA_DIR="/data/kingbase/data"
KSQL="ksql -U system -d production -t -A -c"
echo "===== 磁盤使用 ====="
df -h $DATA_DIR
echo ""
echo "===== 數(shù)據(jù)庫大小 ====="
$KSQL "SELECT datname, sys_size_pretty(sys_database_size(datname))
FROM sys_database ORDER BY sys_database_size(datname) DESC;"
echo ""
echo "===== TOP 10 大表 ====="
$KSQL "SELECT schemaname||'.'||relname AS table_name,
sys_size_pretty(sys_total_relation_size(relid)) AS total_size,
n_live_tup AS row_count
FROM sys_stat_user_tables
ORDER BY sys_total_relation_size(relid) DESC LIMIT 10;"
echo ""
echo "===== 未使用的索引 ====="
$KSQL "SELECT schemaname||'.'||indexrelname AS index_name,
sys_size_pretty(sys_relation_size(indexrelid)) AS size,
idx_scan AS scan_count
FROM sys_stat_user_indexes
WHERE idx_scan = 0
ORDER BY sys_relation_size(indexrelid) DESC LIMIT 10;"
echo ""
echo "===== 表膨脹估算 ====="
$KSQL "SELECT schemaname||'.'||relname AS table_name,
n_dead_tup AS dead_tuples,
round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_ratio
FROM sys_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC LIMIT 10;"
這種腳本配合 crontab 每天跑一次,結(jié)果發(fā)個(gè)郵件或者寫到共享目錄里,巡檢效率會高很多。
常見問題與排查思路
最后記幾個(gè)實(shí)際遇到過的典型問題。
連接數(shù)打滿
應(yīng)用突然連不上數(shù)據(jù)庫,報(bào)錯(cuò) “sorry, too many clients already”。第一反應(yīng)是查 max_connections,但光加大這個(gè)參數(shù)治標(biāo)不治本。
-- 看看到底是哪些連接占著 SELECT state, count(*) FROM sys_stat_activity GROUP BY state; -- 看各個(gè)來源 IP 的連接數(shù) SELECT client_addr, count(*) FROM sys_stat_activity WHERE client_addr IS NOT NULL GROUP BY client_addr ORDER BY 2 DESC;
常見原因有這么幾種:應(yīng)用端連接池沒配好,連接泄漏了沒歸還;idle in transaction 的連接太多占著坑不干活;max_connections 本身設(shè)太小了。如果并發(fā)確實(shí)高,在前面擋一層連接池中間件比直接加 max_connections 靠譜得多。
慢查詢定位
用戶反饋某個(gè)功能特別慢。先在日志里找慢 SQL——前面配置了 log_min_duration_statement = 1000,超過 1 秒的查詢都會記到日志里。日志文件在數(shù)據(jù)目錄下的 sys_log 子目錄里,用 grep 搜 “duration” 關(guān)鍵字就能快速定位。當(dāng)然,如果你的慢查詢閾值設(shè)得比較低(比如 500 毫秒),日志量會比較大,建議只在排查問題的時(shí)候臨時(shí)調(diào)低,排查完了改回來。
-- 也可以直接從視圖里查 SELECT query, calls, total_time, mean_time, rows FROM sys_stat_statements WHERE mean_time > 500 ORDER BY mean_time DESC LIMIT 20;
拿到慢 SQL 之后用 EXPLAIN ANALYZE 看執(zhí)行計(jì)劃,重點(diǎn)關(guān)注是不是走了全表掃描、Nested Loop 嵌套層數(shù)是不是太多、有沒有臨時(shí)文件排序。大多數(shù)性能問題都是缺索引或者索引選錯(cuò)了導(dǎo)致的。
-- 看執(zhí)行計(jì)劃 EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT d.device_name, avg(s.temperature) AS avg_temp FROM sensor_data s JOIN device_info d ON s.device_id = d.id WHERE s.record_time > now() - INTERVAL '7 days' GROUP BY d.device_name ORDER BY avg_temp DESC;
VACUUM 相關(guān)問題
KES 用 MVCC 機(jī)制管理數(shù)據(jù)版本,刪除和更新操作不會真正移除舊數(shù)據(jù)行,而是標(biāo)記為死元組。VACUUM 負(fù)責(zé)回收這些死元組占用的空間。如果 VACUUM 跟不上寫入速度,表就會持續(xù)膨脹,查詢性能也會下降——因?yàn)閽呙璧臅r(shí)候要跳過大量的死元組,白白浪費(fèi) IO。
這個(gè)問題平時(shí)不容易發(fā)現(xiàn),等到表膨脹得很厲害了才會暴露出來。我碰到過一個(gè)表,業(yè)務(wù)上每天大量更新,autovacuum 一直追不上寫入速度,半年下來表的物理大小漲了將近三倍,但實(shí)際有效數(shù)據(jù)行只多了 30%。
-- 查看哪些表需要 VACUUM
SELECT schemaname||'.'||relname AS table_name,
n_dead_tup AS dead_tuples,
n_live_tup AS live_tuples,
last_vacuum, last_autovacuum
FROM sys_stat_user_tables
WHERE n_dead_tup > 10000
AND n_dead_tup > n_live_tup * 0.1
ORDER BY n_dead_tup DESC;
-- 手動 VACUUM 某個(gè)表(帶分析)
VACUUM ANALYZE sensor_data;
-- 看 autovacuum 是否正常工作
SELECT pid, query, now() - query_start AS duration
FROM sys_stat_activity
WHERE query LIKE 'autovacuum%'
ORDER BY duration DESC;
autovacuum 一般不用手動干預(yù),但對于寫入量特別大的表,默認(rèn)的 autovacuum 參數(shù)可能不夠激進(jìn),可以適當(dāng)調(diào)大 autovacuum_vacuum_scale_factor 和 autovacuum_analyze_scale_factor。
總結(jié)
這篇文章覆蓋了 KES 數(shù)據(jù)庫從安裝到日常運(yùn)維的主要操作環(huán)節(jié)。部署環(huán)節(jié)的關(guān)鍵是環(huán)境初始化和參數(shù)調(diào)優(yōu),特別是內(nèi)存參數(shù)和兼容模式的選擇,這兩項(xiàng)一旦定下來后面改動成本很高;安全方面三權(quán)分立和 TDE 是 KingbaseES 比較有特色的功能,政務(wù)和金融項(xiàng)目基本都要用上,審計(jì)日志的存儲規(guī)劃也要提前做好;備份恢復(fù)要形成制度,全量加增量的組合策略加上定期驗(yàn)證,確保關(guān)鍵時(shí)刻真的能恢復(fù)出來;監(jiān)控診斷靠 KWR 和 KSH 這兩個(gè)內(nèi)置工具就能搞定大部分場景,配合一個(gè)簡單的巡檢腳本基本夠用了。
KES 這幾年迭代速度挺快,從 V8 到 V9 在性能和易用性上都有明顯進(jìn)步。用的過程中遇到問題多看官方文檔,文檔中心 help.kingbase.com.cn 上的內(nèi)容還是比較全的。另外社區(qū)里也有不少實(shí)踐經(jīng)驗(yàn)可以參考,碰到坑的時(shí)候搜一搜往往能找到類似的解決思路。
數(shù)據(jù)庫運(yùn)維這個(gè)活兒說到底就是"預(yù)防為主、治療為輔"。備份做好、監(jiān)控到位、定期巡檢,大部分問題都能在釀成事故之前處理掉。與其花三天時(shí)間恢復(fù)一個(gè)本可以避免的故障,不如每天花十分鐘看看監(jiān)控?cái)?shù)據(jù)。這話雖然老生常談,但真正做到的人確實(shí)不多。共勉。
到此這篇關(guān)于KingbaseES數(shù)據(jù)庫開發(fā)運(yùn)維:部署、安全、備份與監(jiān)控實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)KingbaseES開發(fā)運(yùn)維筆記內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
數(shù)據(jù)庫刪除完全重復(fù)和部分關(guān)鍵字段重復(fù)的記錄
重復(fù)記錄分為兩種,第一種是完全重復(fù)的記錄,也就是所有字段均重復(fù)的記錄,第二種是部分關(guān)鍵字段重復(fù)的記錄,例如Name字段重復(fù),而其它字段不一定重復(fù)或都重復(fù)。2008-05-05
如何使用dbeaver遷移數(shù)據(jù)庫(含完整圖文教程)
DBeaver提供了一系列豐富的數(shù)據(jù)庫操作功能,用戶可以通過圖形用戶界面執(zhí)行SQL查詢,這些查詢可以手動編寫或利用內(nèi)置的編輯器自動完成,這篇文章主要介紹了如何使用dbeaver遷移數(shù)據(jù)庫的相關(guān)資料,需要的朋友可以參考下2026-04-04
銀河麒麟V10安裝達(dá)夢8數(shù)據(jù)庫詳細(xì)操作過程及避坑
在數(shù)字化轉(zhuǎn)型的浪潮下,數(shù)據(jù)庫作為企業(yè)核心數(shù)據(jù)存儲與管理的基石,其安全性、穩(wěn)定性和自主可控性顯得尤為重要,這篇文章主要介紹了銀河麒麟V10安裝達(dá)夢8數(shù)據(jù)庫詳細(xì)操作過程及避坑的相關(guān)資料,需要的朋友可以參考下2026-04-04
Dbeaver如何從一個(gè)數(shù)據(jù)庫復(fù)制表到另外一個(gè)數(shù)據(jù)庫
在數(shù)據(jù)庫管理中,導(dǎo)出表是一項(xiàng)常見操作,可以通過特定的工具或數(shù)據(jù)庫自帶的功能實(shí)現(xiàn),步驟包括:1.在數(shù)據(jù)庫管理軟件中找到需導(dǎo)出的表,右鍵選擇導(dǎo)出數(shù)據(jù),2.選擇目標(biāo)數(shù)據(jù)庫,并進(jìn)行表映射設(shè)置,3.根據(jù)需求調(diào)整導(dǎo)出參數(shù),4.執(zhí)行操作完成數(shù)據(jù)導(dǎo)出2024-10-10
2024 Navicat Premium最新版簡體中文版激活永久圖文詳細(xì)教程(親測可用)
這篇文章主要介紹了2024 Navicat Premium最新版簡體中文版激活永久圖文詳細(xì)教程,文章通過圖文結(jié)合的方式給大家講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-09-09
Linux下mysql數(shù)據(jù)庫的創(chuàng)建導(dǎo)入導(dǎo)出 及一些基本指令
這篇文章主要介紹了Linux數(shù)據(jù)庫的創(chuàng)建 導(dǎo)入導(dǎo)出 以及一些基本指令,需要的朋友可以參考下2019-08-08
DBeaver連接GBase數(shù)據(jù)庫的簡單步驟記錄
DBeaver數(shù)據(jù)庫連接工具,是我用了這么久最好用的一個(gè)數(shù)據(jù)庫連接工具,擁有的優(yōu)點(diǎn),支持的數(shù)據(jù)庫多、快捷鍵很贊、導(dǎo)入導(dǎo)出數(shù)據(jù)非常方便,下面這篇文章主要給大家介紹了關(guān)于DBeaver連接GBase數(shù)據(jù)庫的簡單步驟,需要的朋友可以參考下2024-03-03

