海量数据库 Vastbase G100 V2.2 DBA 日常操作运维手册
覆盖范围:数据库启停、用户管理(创建/改密/锁定/删除)、授权与取消授权、建库、建表、视图、索引、默认授权。
阅读约定:代码块中带 # 前缀的行表示以 root 用户输入的命令,带 $ 前缀的行表示以 vastbase 系统用户输入的命令(业务用户连接通过 PGPASSWORD 环境变量区分并在命令中注明),其余行均为实际输出。文中所有口令一律以 ****** 表示,执行时替换为实际口令即可。
一、环境与软件说明
1.1 硬件与操作系统
| 项目 | 值 |
|---|---|
| 主机名 / IP | kyinLinx / 10.168.1.175 |
| 操作系统 | Kylin Linux Advanced Server V10 (Sun) |
| CPU | 8 核 Intel® Xeon® CPU E5-2699 v4 @ 2.20GHz |
| 内存 | 16 GB(实际 15 Gi) |
| 数据盘 | /dev/mapper/kals-backup,xfs,30G,挂载 /backup |
# free -h
total used free shared buff/cache available
Mem: 15Gi 3.2Gi 2.8Gi 59Mi 9.3Gi 11Gi
Swap: 7.9Gi 204Mi 7.7Gi
# df -h /backup
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/kals-backup 30G 1.7G 29G 6% /backup
1.2 数据库软件版本
$ vsql --version
vsql (Vastbase G100 V2.2 (Build 19) Release) compiled at 2026-06-27 14:26:11 commit 32736 last mr
$ vb_ctl --version
vb_ctl (Vastbase G100 V2.2 (Build 19) Release) compiled at 2026-06-27 14:26:11 commit 32736 last mr
连接进去再看内核版本与兼容模式——G100 的内核版本号沿 PostgreSQL 报告,兼容模式 A 即 Oracle 兼容:
$ vsql -d postgres -p 5432 -Atc 'select version();'
PostgreSQL 9.2.4 on x86_64-pc-linux-gnu, compiled by g++ (GCC) 7.3.0, 64-bit
$ vsql -d postgres -p 5432 -Atc 'show sql_compatibility;'
A
1.3 实例关键信息
| 项目 | 值 |
|---|---|
| systemd 服务名 | vastbase-server(enabled,开机自启) |
| 数据目录 | /backup/vastbase/data |
| 软件目录 | /home/vastbase/local/vastbase |
| 监听端口 | 5432(listen_addresses=‘*’) |
| 兼容模式 | A(Oracle 兼容) |
| License | 90 天试用版,有效期至 2026-12-08(/etc/vastbase/.license) |
systemd 单元定义值得贴出来,后面启停章节的两个坑都藏在里面:
# systemctl cat vastbase-server
# /etc/systemd/system/vastbase-server.service
[Unit]
Description=Vastbase G100 Database Server
After=network.target
[Service]
Type=forking
User=vastbase
Group=vastbase
ExecStart=/bin/bash -lc "/home/vastbase/local/vastbase/bin/vb_ctl start -D /backup/vastbase/data -t 120"
ExecStop=/bin/bash -lc "/home/vastbase/local/vastbase/bin/vb_ctl stop -D /backup/vastbase/data -m fast -t 120"
ExecReload=/bin/bash -lc "/home/vastbase/local/vastbase/bin/vb_ctl restart -D /backup/vastbase/data -t 120"
TimeoutSec=300
[Install]
WantedBy=multi-user.target
看清楚了:Type=forking,ExecStart/ExecStop 都是拿 bash -lc 包了一层 vb_ctl。也就是说 systemd 只是 vb_ctl 的壳,这个结构决定了后面"手工 vb_ctl 与 systemctl 混用会互踩"的坑。
1.4 三权分立账户
G100 默认三权分立:初始化超级用户 vastbase(安全设计默认禁止远程登录)、系统管理员 vbadmin、安全管理员 vbsso、审计管理员 vbaudit。用 pg_roles 盘点实例角色(口令不在系统表里,不存在泄露问题):
$ vsql -d postgres -p 5432 -c "select rolname, rolsuper, rolcreaterole, rolcreatedb, rolcanlogin, rolconnlimit from pg_roles order by rolname;"
rolname | rolsuper | rolcreaterole | rolcreatedb | rolcanlogin | rolconnlimit
--------------------------+----------+---------------+-------------+-------------+--------------
bizapp | f | f | f | t | -1
gs_role_account_lock | f | f | f | f | -1
gs_role_copy_files | f | f | f | f | -1
gs_role_directory_create | f | f | f | f | -1
gs_role_directory_drop | f | f | f | f | -1
gs_role_pldebugger | f | f | f | f | -1
gs_role_replication | f | f | f | f | -1
gs_role_signal_backend | f | f | f | f | -1
gs_role_tablespace | f | f | f | f | -1
vastbase | t | t | t | t | -1
vb_read_all_settings | f | f | f | f | -1
vbadmin | t | t | t | t | -1
vbaudit | f | t | f | t | -1
vbsso | f | t | f | t | -1
(14 行记录)
14 个角色里 8 个 gs_role_* 是系统内置功能角色(不能登录),真正管事的是四个人:vastbase(超级用户,本机免密)、vbadmin(远程运维用)、vbsso/vbaudit(安全与审计,rolcreaderole=t 但 rolsuper=f,权责被刻意收窄——这就是三权分立的落点)。
本次手册的操作账号是一对演示用户:业务用户 ops_demo、只读用户 ops_ro(下文创建),全程不碰四权账户。
1.5 口令策略(改密前必须知道)
改密演示之前先把口令策略参数摸清,否则报错都看不懂。这些值直接从 pg_settings 取:
$ vsql -d postgres -p 5432 -Atc "select name||' = '||setting from pg_settings where name like 'password%' or name in ('enable_separation_of_duty','vb_enable_separation_of_duty') order by name;"
| 参数 | 值 | 含义 |
|---|---|---|
| password_min_length / max_length | 8 / 32 | 口令长度区间 |
| password_min_digital / lowercase / uppercase / special | 0 / 0 / 0 / 0 | 未强制字符类别(password_policy=1 只做基本校验) |
| password_policy | 1 | 口令复杂度策略等级 |
| password_reuse_max | 3 | 最近 3 次用过的口令不许再用 |
| password_reuse_time | 90 | 90 天内用过的口令不许再用 |
| password_lock_time | 1440 | 连续失败锁定时长(分钟),1440=24 小时 |
| password_effect_time | 36500 | 口令有效期(天) |
| password_notify_time | 7 | 到期前 7 天开始提醒 |
| password_encryption_type | 1 | 存储加密方式:md5 |
| password_force_alter | off | 不强制首次登录改密 |
| enable_separation_of_duty | off | 三权分立增强开关(本实例为安装器默认关闭状态) |
记住 password_reuse_max=3 和 password_reuse_time=90,改密章节会亲眼看到它们怎么拦人。
二、前置检查
每次做 DBA 操作前,先花 10 秒确认实例活着、版本对、监听在:
# systemctl is-active vastbase-server
active
# systemctl is-enabled vastbase-server
enabled
# ss -lntp | grep ':5432'
LISTEN 0 3000 0.0.0.0:5432 0.0.0.0:* users:(("vastbase",pid=1191142,fd=14))
LISTEN 0 3000 [::]:5432 [::]:* users:(("vastbase",pid=1191142,fd=15))
$ vsql -d postgres -p 5432 -Atc 'select pg_postmaster_start_time();'
2026-09-13 23:51:50.476836+08
判定点:is-active 返回 active、5432 有 vastbase 进程监听、启动时间与最近一次启停操作吻合,三样齐了才继续。
盘点现有数据库:
$ vsql -d postgres -p 5432 -c '\l'
数据库库列表
名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限
-----------+----------+----------+-------------+-------------+-----------------------
bizdb | bizapp | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =Tc/bizapp +
| | | | | bizapp=CTc/bizapp +
| | | | | bizapp=APm/bizapp
postgres | vastbase | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | vastbase | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/vastbase +
| | | | | vastbase=CTc/vastbase
template1 | vastbase | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/vastbase +
| | | | | vastbase=CTc/vastbase
vastbase | vastbase | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
(5 行记录)
存取权限(datacl)这一列后面讲授权时要用:=Tc/bizapp 表示 PUBLIC 对 bizdb 有 T(临时表)和 c(连接)权限,bizapp=CTc/bizapp 表示属主全权。数据库列表是后续建库、授权章节的基线。
2.1 认证机制:文件写 trust,实测却要密码
pg_hba.conf 内容如下:
# grep -v '^#' /backup/vastbase/data/pg_hba.conf | grep -v '^[[:space:]]*$'
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all 0.0.0.0/0 md5
按这份文件,本地 socket 和 127.0.0.1 应该免密。但实测普通用户本地直连照样要口令——不输、乱输都被拒:
$ vsql -d opsdb -p 5432 -U ops_demo -Atc 'select current_user;' </dev/null
用户 ops_demo 的密码:
vsql: 致命错误: 用户名或密码错误,登录拒绝
(exit=2)
而 vastbase 操作系统用户登录 vsql 却全程免密。查环境变量就明白了:
$ echo "PGHOST=[$PGHOST] PGUSER=[$PGUSER] PGPORT=[$PGPORT]"
PGHOST=[] PGUSER=[vastbase] PGPORT=[5432]
安装时给 vastbase 用户的 profile 里固化了 PGUSER=vastbase,配合本地 trust 规则实现管理员本机免密;换成其他用户名(如 ops_demo)就落到口令校验上。结论以实测为准:这台实例上除 vastbase 本机免密外,任何用户任何通道都要口令。另外,PostgreSQL 用来核对 hba 的 pg_hba_file_rules 视图在 G100 这个内核上不存在,想在线核对规则只能看文件本身:
$ vsql -d postgres -p 5432 -c "select * from pg_hba_file_rules;"
错误: 关系 "pg_hba_file_rules" 不存在在 node1
这是与原生 PG 运维习惯的第一个差异,提前记住,省得排查时怀疑人生。
远程连接走 md5,PGPASSWORD 环境变量传口令(vsql 会提醒一句安全风险,脚本场景可接受,交互场景建议口令手工输入):
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb -Atc 'select current_user;'
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
ops_demo
三、数据库启停
启停是 DBA 最常见也最不能出事的操作。这台实例有两条路径:systemd 托管(systemctl,ExecStart/ExecStop 的本质还是调 vb_ctl)和 vb_ctl 手工直操。日常一律走 systemctl,vb_ctl 只在 systemd 异常时救场——原因看完 3.4 节的事故现场就懂。
3.1 启动:systemctl start
先看"库是停着的"长什么样(is-active 返回非 0、状态 inactive(dead)、端口无监听):
# systemctl is-active vastbase-server
inactive
(exit=3)
# systemctl status vastbase-server --no-pager
● vastbase-server.service - Vastbase G100 Database Server
Loaded: loaded (/etc/systemd/system/vastbase-server.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Fri 2026-09-11 21:10:22 CST; 2 days ago
Main PID: 355697 (code=exited, status=0/SUCCESS)
# ss -lntp | grep ':5432'
(无监听)
启动:
# systemctl start vastbase-server
(exit=0)
命令本身没有输出,验证要靠自己,三步走:
# systemctl status vastbase-server --no-pager
● vastbase-server.service - Vastbase G100 Database Server
Loaded: loaded (/etc/systemd/system/vastbase-server.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2026-09-13 23:51:51 CST; 3s ago
Process: 1190256 ExecStart=/bin/bash -lc /home/vastbase/local/vastbase/bin/vb_ctl start -D /backup/vastbase/data -t 120 (code=exited, status=0/SUCCESS)
Main PID: 1190277 (vastbase)
Tasks: 69 (limit: 100245)
# ss -lntp | grep ':5432'
LISTEN 0 3000 0.0.0.0:5432 0.0.0.0:* users:(("vastbase",pid=1190277,fd=14))
LISTEN 0 3000 [::]:5432 [::]:* users:(("vastbase",pid=1190277,fd=15))
$ vb_ctl status -D /backup/vastbase/data
[2026-09-13 23:51:54.915][1190359][][vb_ctl]: vb_ctl status,数据目录是 /backup/vastbase/data
vb_ctl: 正在运行服务器进程(PID: 1190277)
/home/vastbase/local/vastbase/bin/vastbase "-D" "/backup/vastbase/data"
判定点:Active: active (running)、5432 双栈监听、vb_ctl status 报出主进程 PID。从敲下命令到可连接,实测 7 秒左右(23:51:48 发起 → 23:51:55 vsql 通)。
3.2 停库:systemctl stop 与"停了之后客户端什么样"
停库前先确认没有长事务在跑(pg_stat_activity 里除自己外没有 active 查询),然后停:
# systemctl stop vastbase-server
(exit=0,fast 模式,回滚未决事务后退出)
# systemctl is-active vastbase-server
inactive
(exit=3)
# ss -lntp | grep ':5432'
(5432 无监听)
停库瞬间客户端的报错长这样,值班时认准它:
$ vsql -d postgres -p 5432 -Atc 'select 1;'
连接到失败 Unknown:5432.
(exit=2)
本次演练从 stop 到重新可连接,实际中断 8 秒(23:53:57 → 23:54:05),全程数据无损。
3.3 重启:systemctl restart
参数改完 postgresql.conf 后的常规动作,一条命令完成停+启:
# systemctl restart vastbase-server
(exit=0)
# systemctl is-active vastbase-server
active
$ vsql -d postgres -p 5432 -Atc 'select pg_postmaster_start_time();'
2026-09-14 09:57:37.807289+08
判定点:pg_postmaster_start_time() 变成刚才的时间点,说明实例真的换了新进程,不是假活。
3.4 vb_ctl 手工启停(辅线):能干,但别和 systemd 混用
systemd 挂了的极端场景才用这条路径,而且用完必须想清楚状态归谁管。先停掉 systemd 托管的库,然后用 vastbase 用户手工拉起:
# systemctl stop vastbase-server
# systemctl is-active vastbase-server
inactive
$ vb_ctl start -D /backup/vastbase/data -t 60
[2026-09-14 07:33:45.588][1207892][][vb_ctl]: vb_ctl started,数据目录是 /backup/vastbase/data
[2026-09-14 07:33:45.754][1207892][][vb_ctl]: 等待服务端进程启动 ...
(中间为 License 加载、内存规划等常规启动日志,与判断无关,此处省略)
许可证信息:
License 序列号:e72d8ca4-6AA1599D
License 类型:临时
License 过期时间:2026-12-08 21:05:33
license文件目录:/etc/vastbase/.license
[2026-09-14 07:33:48.227][1207892][][vb_ctl]: 完成
[2026-09-14 07:33:48.227][1207892][][vb_ctl]: 服务端进程已经启动 (/backup/vastbase/data)
# ss -lntp | grep ':5432'
LISTEN 0 3000 0.0.0.0:5432 0.0.0.0:* users:(("vastbase",pid=1207913,fd=14))
库确实活了(PID 1207913)。但此时问 systemd,它一脸茫然:
# systemctl is-active vastbase-server
inactive
(exit=3)
因为手工 vb_ctl 起的进程没经过 ExecStart,systemd 的账本上这个服务还是死的。危险在这里才开始——如果值班同事看到 inactive 顺手补了一刀 systemctl start,systemd 的处理顺序是:发现 ExecStart 的 vb_ctl 报"目录已在运行"→ 按失败处理 → 顺手执行 ExecStop 把你手工拉起的库停掉。实测现场:
# systemctl start vastbase-server
(exit=0,但库被停了)
# systemctl status vastbase-server --no-pager
● vastbase-server.service - Vastbase G100 Database Server
Loaded: loaded (/etc/systemd/system/vastbase-server.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2026-09-14 07:33:52 CST; 8ms ago
Process: 1208037 ExecStop=/bin/bash -lc /home/vastbase/local/vastbase/bin/vb_ctl stop -D /backup/vastbase/data -m fast -t 120 (code=exited, status=0/SUCCESS)
Process: 1208014 ExecStart=/bin/bash -lc /home/vastbase/local/vastbase/bin/vb_ctl start -D /backup/vastbase/data -t 120 (code=exited, status=0/SUCCESS)
Main PID: 1191142 (code=exited, status=0/SUCCESS)
看清楚这两行:ExecStart 和 ExecStop 双双 SUCCESS,服务却是 inactive(dead)——systemd 认为它"启动失败后清理成功",实际效果是把正在运行的库干掉了。此时再想用 vb_ctl 收尾,PID 文件已经被 ExecStop 清走,报错又不一样:
$ vb_ctl stop -D /backup/vastbase/data -m fast -t 60
[2026-09-14 07:33:52.556][1208063][][vb_ctl]: vb_ctl stopped ,数据目录是 /backup/vastbase/data
[2026-09-14 07:33:52.556][1208063][][vb_ctl]: PID 文件 "/backup/vastbase/data/postmaster.pid" 不存在
[2026-09-14 07:33:52.556][1208063][][vb_ctl]: 服务进程是否正在运行?
(exit=1)
正确归位姿势:既然库已被停掉,直接交回 systemd:
# systemctl start vastbase-server
(exit=0)
# systemctl is-active vastbase-server
active
$ vsql -d postgres -p 5432 -Atc 'select pg_postmaster_start_time();'
2026-09-14 07:33:54.049923+08
三条铁律:
systemctl is-active显示 inactive 不代表进程不在,先ss -lntp | grep 5432+vb_ctl status核实再动手;- 手工 vb_ctl 起的库,要么用 vb_ctl 停,要么先 vb_ctl 停干净再 systemctl start,绝不倒手混用;
- 判断库里有没有进程,认 PID 文件
/backup/vastbase/data/postmaster.pid和端口监听,别信单一来源。
3.5 开机自启
服务已 enable,装机后验证一次即可:
# systemctl is-enabled vastbase-server
enabled
四、用户管理
管理动作全部以 vastbase 用户本机免密执行(生产上等价于用 vbadmin 远程执行,语法相同)。建用户只举 ops_demo(业务读写)和 ops_ro(只读校验)两个例子,口令以 ****** 代称。
4.1 创建用户
$ vsql -d postgres -p 5432 -c "CREATE USER ops_demo WITH PASSWORD '******';"
CREATE ROLE
$ vsql -d postgres -p 5432 -c "CREATE USER ops_ro WITH PASSWORD '******';"
CREATE ROLE
注意回显是 CREATE ROLE 而不是 CREATE USER——USER 本质就是带登录属性的 ROLE。立即核验属性:
$ vsql -d postgres -p 5432 -c "select rolname,rolsuper,rolcreaterole,rolcreatedb,rolcanlogin from pg_roles where rolname like 'ops%' order by rolname;"
rolname | rolsuper | rolcreaterole | rolcreatedb | rolcanlogin
----------+----------+---------------+-------------+-------------
ops_demo | f | f | f | t
ops_ro | f | f | f | t
(2 行记录)
判定点:rolcanlogin=t,其余全 f——最小权限起步,建库建角色属性后面单独授予。
口令不满足策略会被当场拒绝,比如长度不足 8 位:
$ vsql -d postgres -p 5432 -c "CREATE USER bad_demo WITH PASSWORD '******';"
错误: 密码必须包含至少8个字符。
(vsql 对 SQL 层错误默认返回 0,bad_demo 实际未创建,靠回显判断成败)
4.2 改密(管理员改 vs 用户本人改)
管理员改(忘记旧口令场景):
$ vsql -d postgres -p 5432 -c "ALTER USER ops_demo WITH PASSWORD '******';"
ALTER ROLE
改完立即用新口令验证,旧口令应当被拒:
$ PGPASSWORD='旧口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb -Atc 'select 1;'
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
vsql: 致命错误: 用户名或密码错误,登录拒绝
(exit=2)
$ PGPASSWORD='新口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb -Atc 'select count(*) as emp_rows from ops.emp;'
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
emp_rows
----------
5
(1 行记录)
用户本人改:语法是 Oracle 风格的 IDENTIFIED BY,实测这台实例上必须带 REPLACE 旧口令,不带直接被拒。这是本次实操踩到的实打实的坑(G100 V2.2 Build19 32736 实测行为),现场还原:
$ PGPASSWORD='旧口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "ALTER USER ops_demo IDENTIFIED BY '新口令';"
错误: 旧密码不能为空,请用'replace'语法输入旧密码。
(stdout 显示 exit=0,实际口令未变——见下方红线)
写对的样子:
$ PGPASSWORD='旧口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "ALTER USER ops_demo IDENTIFIED BY '新口令' REPLACE '旧口令';"
ALTER ROLE
$ PGPASSWORD='旧口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb -Atc "select 'should-not-see';"
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
vsql: 致命错误: 用户名或密码错误,登录拒绝
(exit=2,旧口令已失效)
$ PGPASSWORD='新口令' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb -Atc 'select current_user;'
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
ops_demo
(exit=0)
同一个会话里还撞上口令复用策略的现行——改回最近用过的口令被拒:
错误: 新密码不能和旧密码相同
对应 1.5 节的 password_reuse_max=3 / password_reuse_time=90:最近 3 个口令、90 天内用过的都换不回去。
红线:vsql 遇到 SQL 层错误时 exit code 依然是 0(实测:连接失败/账户锁定返回 2,SQL 报错默认返回 0,加
-v ON_ERROR_STOP=1才返回 3)。上面的错误改密脚本要是只看退出码就会漏掉。自动化脚本判定成败必须看回显文本或加ON_ERROR_STOP,这条贯穿全文所有操作。
4.3 锁定与解锁
登录失败连续超限自动锁定(锁定时长=1.5 节的 password_lock_time=1440 分钟),人工锁定解锁用 ACCOUNT 子句:
$ vsql -d postgres -p 5432 -c "ALTER USER ops_ro ACCOUNT LOCK;"
ALTER ROLE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb -Atc 'select 1;'
警告: 使用PGPASSWORD环境变量连接数据库存在安全风险
vsql: 致命错误: 账户被锁定
(exit=2)
$ vsql -d postgres -p 5432 -c "ALTER USER ops_ro ACCOUNT UNLOCK;"
ALTER ROLE
判定点:锁定后报错文本是"账户被锁定"而不是"用户名或密码错误"——值班时靠这句话区分"密码错了"还是"账号被锁了"。
4.4 删除用户:先处理依赖
有依赖对象的用户直接删会被拒,报错把依赖列得明明白白:
$ vsql -d postgres -p 5432 -c "DROP USER ops_demo;"
错误: 无法删除"ops_demo"因为有其它对象依赖它
描述: 数据库 opsdb的属主
在数据库 opsdb中的3个对象
标准删除流程:先把名下对象(库/表/视图)移交或删除,再删人。完整走一遍一次性账号的生灭:
$ vsql -d postgres -p 5432 -c "CREATE USER ops_tmp WITH PASSWORD '******';"
CREATE ROLE
$ vsql -d postgres -p 5432 -c "CREATE DATABASE opsdb_tmp OWNER ops_tmp;"
CREATE DATABASE
$ vsql -d postgres -p 5432 -Atc "select datname from pg_database where datname='opsdb_tmp';"
opsdb_tmp
$ vsql -d postgres -p 5432 -c "DROP DATABASE opsdb_tmp;"
DROP DATABASE
$ vsql -d postgres -p 5432 -c "DROP USER ops_tmp;"
DROP ROLE
顺序必须是先删库(或 REASSIGN/移交对象)后删人,反过来就是上面的依赖报错。
4.5 改名与属主转移(顺手补充)
库的属主转移用 ALTER DATABASE ... OWNER TO,配合删人场景把对象移交出去再删用户,比逐个 DROP 稳妥。实测 opsdb 的属主本来就是 ops_demo,同属主执行语法验证:
$ vsql -d postgres -p 5432 -c "ALTER DATABASE opsdb OWNER TO ops_demo;"
ALTER DATABASE
$ vsql -d postgres -p 5432 -c "select datname,datdba::regrole as owner from pg_database where datname='opsdb';"
datname | owner
---------+----------
opsdb | ops_demo
(1 行记录)
五、创建数据库与 schema
5.1 建库
CREATE DATABASE 不能在事务块里执行,直接单条发:
$ vsql -d postgres -p 5432 -c "CREATE DATABASE opsdb OWNER ops_demo ENCODING 'UTF8';"
CREATE DATABASE
$ vsql -d postgres -p 5432 -c "select datname,datdba::regrole as owner,datacl from pg_database where datname='opsdb';"
datname | owner | datacl
---------+----------+-------------------------------------------------------
opsdb | ops_demo | {=T/ops_demo,ops_demo=CTc/ops_demo}
(1 行记录)
判定点:owner 是建库时指定的用户;datacl 初始只有属主全权(CTc)和 PUBLIC 的默认项(=T/),权限从零开始,后面 6.1 会把 PUBLIC 的 CONNECT 收掉做库级隔离。
5.2 建 schema 与 search_path
业务对象建议收进业务 schema,不散在 public:
$ vsql -d opsdb -p 5432 -c "CREATE SCHEMA ops AUTHORIZATION ops_demo;"
CREATE SCHEMA
会话内切 schema 用 SET search_path TO ops;,写 SQL 就不用带前缀了。后文 ops_demo 的所有操作都以此为前提。
六、建表、视图、索引(业务用户实操)
这一节全部用业务用户 ops_demo 自己动手(经 md5 + PGPASSWORD 连接),属主归位,不需要管理员代劳。
6.1 建表与插数
$ SET search_path TO ops;
$ CREATE TABLE emp (
id int PRIMARY KEY,
name varchar(50) NOT NULL,
dept varchar(30),
salary numeric(10,2),
hire_date date NOT NULL
);
CREATE TABLE
注意: CREATE TABLE / PRIMARY KEY 将要为表 "emp" 创建隐含索引 "emp_pkey"
$ INSERT INTO emp VALUES
(1,'张三','运维',8500.00,'2024-03-01'),
(2,'李四','开发',9200.00,'2023-07-15'),
(3,'王五','运维',7600.00,'2025-01-10'),
(4,'赵六','测试',6800.00,'2024-11-20');
INSERT 0 4
主键自带隐含索引 emp_pkey,回显里明确提示——这意味着主键列不用再手工建索引。
6.2 建索引
$ CREATE INDEX idx_emp_dept ON emp(dept);
CREATE INDEX
$ CREATE INDEX idx_emp_salary ON emp(salary);
CREATE INDEX
索引定义核验:
$ \di
关联列表
架构模式 | 名称 | 型别 | 拥有者 | 表 | 存储
----------+----------------+------+----------+-----+------
ops | emp_pkey | 索引 | ops_demo | emp |
ops | idx_emp_dept | 索引 | ops_demo | emp |
ops | idx_emp_salary | 索引 | ops_demo | emp |
(3 行记录)
等价 SQL 视角(自动化脚本用这个更稳):
$ select indexname, indexdef from pg_indexes where schemaname='ops' order by indexname;
indexname | indexdef
----------------+-----------------------------------------------------------------------------------
emp_pkey | CREATE UNIQUE INDEX emp_pkey ON ops.emp USING btree (id) TABLESPACE pg_default
idx_emp_dept | CREATE INDEX idx_emp_dept ON ops.emp USING btree (dept) TABLESPACE pg_default
idx_emp_salary | CREATE INDEX idx_emp_salary ON ops.emp USING btree (salary) TABLESPACE pg_default
(3 行记录)
6.3 建视图
$ CREATE VIEW v_emp_high AS
SELECT id, name, dept, salary FROM emp WHERE salary >= 8000;
CREATE VIEW
$ SELECT * FROM v_emp_high ORDER BY id;
id | name | dept | salary
----+------+------+---------
1 | 张三 | 运维 | 8500.00
2 | 李四 | 开发 | 9200.00
(2 行记录)
判定点:4 行原始数据过滤后剩 2 行(≥8000),视图逻辑正确。视图在 G100 里就是 pg_class 里 relkind=‘v’ 的关系,属主跟建它的用户走:
$ \dv
关联列表
架构模式 | 名称 | 型别 | 拥有者 | 存储
----------+------------+------+----------+------
ops | v_emp_high | 视图 | ops_demo |
(1 行记录)
6.4 对象结构总览
\d emp 一次看全表结构、列属性和索引:
$ \d emp
表 "ops.emp"
栏位 | 型别 | 修饰词
-----------+---------------+--------
id | integer | 非空
name | varchar(50) | 非空
dept | varchar(30) |
salary | numeric(10,2) |
hire_date | date | 非空
索引:
"emp_pkey" PRIMARY KEY, btree (id) TABLESPACE pg_default
"idx_emp_dept" btree (dept) TABLESPACE pg_default
"idx_emp_salary" btree (salary) TABLESPACE pg_default
6.5 删除演练:索引/视图/表
临时对象建了就删,删完必须回查确认:
$ CREATE TABLE emp_tmp (id int, note varchar(20));
CREATE TABLE
$ CREATE INDEX idx_emp_tmp_id ON emp_tmp(id);
CREATE INDEX
$ CREATE VIEW v_emp_tmp AS SELECT * FROM emp_tmp;
CREATE VIEW
$ \dv
关联列表
架构模式 | 名称 | 型别 | 拥有者 | 存储
----------+------------+------+----------+------
ops | v_emp_high | 视图 | ops_demo |
ops | v_emp_tmp | 视图 | ops_demo |
(2 行记录)
$ DROP INDEX idx_emp_tmp_id;
DROP INDEX
$ DROP VIEW v_emp_tmp;
DROP VIEW
$ DROP TABLE emp_tmp;
DROP TABLE
$ \dv
关联列表
架构模式 | 名称 | 型别 | 拥有者 | 存储
----------+------------+------+----------+------
ops | v_emp_high | 视图 | ops_demo |
(1 行记录)
注意 DROP VIEW 回显里 DROP VIEW v_emp_tmp 中间多了一个空格——vsql 原样输出,别当成自己敲错了。删除顺序上,视图依赖表时先删视图或加 CASCADE,直接 DROP TABLE 带着依赖视图会报错。
6.6 留存对象终态核验
$ select tablename, tableowner from pg_tables where schemaname='ops' order by tablename;
tablename | tableowner
-----------+------------
emp | ops_demo
(1 行记录)
$ select viewname, viewowner from pg_views where schemaname='ops' order by viewname;
viewname | viewowner
------------+-----------
v_emp_high | ops_demo
(1 行记录)
七、授权与取消授权
权限在 G100 里分三层:库级(CONNECT/CREATE)、schema 级(USAGE/CREATE)、表级(SELECT/INSERT/UPDATE/DELETE…)。排查权限问题时必须逐层往下查,少一层就是"权限不够",报错却不告诉你缺的是哪一层——7.5 节用真实翻车现场说明这一点。
7.1 库级:收回 PUBLIC 的 CONNECT,做库级隔离
新建库默认 PUBLIC 可连,敏感库要收掉:
$ vsql -d opsdb -p 5432 -c "REVOKE CONNECT ON DATABASE opsdb FROM PUBLIC;"
REVOKE
$ vsql -d opsdb -p 5432 -c "GRANT CONNECT ON DATABASE opsdb TO ops_ro;"
GRANT
$ vsql -d postgres -p 5432 -c "select datname,datdba::regrole as owner,datacl from pg_database where datname='opsdb';"
datname | owner | datacl
---------+----------+-------------------------------------------------------
opsdb | ops_demo | {=T/ops_demo,ops_demo=CTc/ops_demo,ops_ro=c/ops_demo}
(1 行记录)
datacl 里 =T/ 只剩默认临时表权限,ops_ro=c/ 是单独授予的连接权——从此没有显式授权的用户连 opsdb 直接被拒。
7.2 表级授权与验证(预期成功段)
给 ops_ro 配只读:先给 schema USAGE(进得去 schema),再给表 SELECT(读得了表):
$ vsql -d opsdb -p 5432 -c "GRANT USAGE ON SCHEMA ops TO ops_ro;"
GRANT
$ vsql -d opsdb -p 5432 -c "GRANT SELECT ON ALL TABLES IN SCHEMA ops TO ops_ro;"
GRANT
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select id,name,dept,salary from ops.emp order by id limit 2;"
id | name | dept | salary
----+------+------+---------
1 | 张三 | 运维 | 8500.00
2 | 李四 | 开发 | 9200.00
(2 行记录)
追加写权限并验证:
$ vsql -d opsdb -p 5432 -c "GRANT INSERT,UPDATE ON ops.emp TO ops_ro;"
GRANT
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "insert into ops.emp values (5,'钱七','运维',8000.00,'2025-02-01');"
INSERT 0 1
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "update ops.emp set salary=8100.00 where id=5;"
UPDATE 1
7.3 取消授权(预期失败段,失败回显即证据)
REVOKE 之后同样的 SQL 立刻被拒——这段失败回显是授权生效的最好证据:
$ vsql -d opsdb -p 5432 -c "REVOKE INSERT,UPDATE ON ops.emp FROM ops_ro;"
REVOKE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "insert into ops.emp values (6,'孙八','测试',7000.00,'2025-03-01');"
错误: 对关系 emp 权限不够
描述: N/A
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "delete from ops.emp where id=5;"
错误: 对关系 emp 权限不够
描述: N/A
把 SELECT 和 schema USAGE 也收掉,读也读不了:
$ vsql -d opsdb -p 5432 -c "REVOKE SELECT ON ALL TABLES IN SCHEMA ops FROM ops_ro;"
REVOKE
$ vsql -d opsdb -p 5432 -c "REVOKE USAGE ON SCHEMA ops FROM ops_ro;"
REVOKE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select * from ops.emp limit 1;"
错误: 对模式 ops 权限不够
第1行select * from ops.emp limit 1;
^
描述: N/A
看这个报错的落点:报的是"对模式 ops 权限不够",不再是表——USAGE 收掉后连 schema 都进不去,表级报错根本轮不到出现。这正是分层排查的现场教材。
授权残留用 relacl 核对,REVOKE 后 ops_ro 的授权项消失、只剩属主:
$ vsql -d opsdb -p 5432 -c "select relname, relacl from pg_class where oid='ops.emp'::regclass;"
relname | relacl
---------+-----------------------------
emp | {ops_demo=arwdDxt/ops_demo}
(1 行记录)
acl 缩写对照:a=INSERT, r=SELECT, w=UPDATE, d=DELETE, D=TRUNCATE, x=REFERENCES, t=TRIGGER。属主 implicitly 全权所以属主项永远在。
7.4 授权基线重建
演示完权限收紧,把 ops_ro 恢复成"只读"基线(后文默认授权验证要用):
$ vsql -d opsdb -p 5432 -c "GRANT USAGE ON SCHEMA ops TO ops_ro;"
GRANT
$ vsql -d opsdb -p 5432 -c "GRANT SELECT ON ops.emp TO ops_ro;"
GRANT
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select * from ops.dept_dic order by id;"
id | dname
----+-------
1 | 运维
2 | 开发
(2 行记录)
7.5 默认授权(ALTER DEFAULT PRIVILEGES):谁执行就对谁的将来对象生效
新表自动授权不想每次手工 GRANT,用默认授权。这里有一个实测出来的大坑:默认授权按"执行者"记账,只对执行者本人将来创建的对象生效。用 vastbase 管理员替 ops_demo 设置,然后 ops_demo 建新表——授权不生效:
$ vsql -d opsdb -p 5432 -c "ALTER DEFAULT PRIVILEGES IN SCHEMA ops GRANT SELECT ON TABLES TO ops_ro;"
ALTER DEFAULT PRIVILEGES
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "create table ops.dept_dic3(id int, dname varchar(30));"
CREATE TABLE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select * from ops.dept_dic3 order by id;"
错误: 对关系 dept_dic3 权限不够
描述: N/A
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "select relname,relacl from pg_class where oid='ops.dept_dic3'::regclass;"
relname | relacl
----------+--------
dept_dic3 |
(1 行记录)
relacl 是空的——管理员设的默认授权挂在管理员名下,跟 ops_demo 建的表无关。正确姿势:由对象创建者本人(ops_demo)执行:
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "ALTER DEFAULT PRIVILEGES IN SCHEMA ops GRANT SELECT ON TABLES TO ops_ro;"
ALTER DEFAULT PRIVILEGES
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "create table ops.dept_dic5(id int, dname varchar(30));"
CREATE TABLE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select * from ops.dept_dic5 order by id;"
id | dname
----+-------
(0 行记录)
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "select relname,relacl from pg_class where oid='ops.dept_dic5'::regclass;"
relname | relacl
----------+-----------------------------------------------
dept_dic5 | {ops_demo=arwdDxt/ops_demo,ops_ro=r/ops_demo}
(1 行记录)
判定点:ops_ro 不经任何单独 GRANT 直接读到新表(空表也返回列头),relacl 里 ops_ro=r/ops_demo 自动出现。
取消默认授权同样由本人执行,再建的新表就不再带授权:
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "ALTER DEFAULT PRIVILEGES IN SCHEMA ops REVOKE SELECT ON TABLES FROM ops_ro;"
ALTER DEFAULT PRIVILEGES
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_demo -d opsdb \
-c "create table ops.dept_dic6(id int);"
CREATE TABLE
$ PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U ops_ro -d opsdb \
-c "select * from ops.dept_dic6 limit 1;"
错误: 对关系 dept_dic6 权限不够
描述: N/A
补一句 dba 层面的教训:7.4 之前那次"ADP 授了却不生效"的排查里,schema USAGE 恰好处于被收回状态,两个原因叠加。权限验证失败时先把变量隔离——确认每一层权限的现状(datacl / nspacl / relacl)再下结论,一次只验一个假设。
7.6 权限排查三板斧
授权问题的排查顺序固定成口诀:
-- 第一板斧:库级,看 CONNECT(datacl)
select datname, datacl from pg_database where datname='opsdb';
-- 第二板斧:schema 级,看 USAGE(nspacl)
select nspname, nspacl from pg_namespace where nspname='ops';
-- 第三板斧:表级,看目标权限(relacl)
select relname, relacl from pg_class where oid='ops.emp'::regclass;
三层 ACL 都有授权项还报权限不够,才去查行级安全/审计策略。
八、实操中真实踩到的坑与解决办法
以下坑全部是本次在真机上撞出来的,每条按"现象 → 排查 → 原因 → 解决"交代,并定性:是我的操作失误、环境/配置问题,还是产品行为差异。版本统一为 Vastbase G100 V2.2 Build 19 (commit 32736),下文不再重复。
坑 1:pg_hba.conf 写着 trust,普通用户实测却要密码 —— 产品行为差异
现象:hba 文件明晃晃写着本地与 127.0.0.1 均 trust(2.1 节),但 ops_demo 本地 socket 直连被要求口令、口令错就被拒;ops_ro 用旧口令走 127.0.0.1 也被拒。trust 规则下这些本应免密直通。
排查:对照 vastbase 用户全程免密——它的 profile 里固化了 PGUSER=vastbase;普通用户无论本地还是回环 TCP 都落口令校验。
原因(定性):产品对 trust 的实现与原生 PostgreSQL 文档语义不一致(G100 对本地认证做了加固或另有策略开关,就这台实例的实测行为而言,除 vastbase 本机免密外一律要口令)。
解决:不迷信文件,运维脚本一律按"非 vastbase 用户都要口令"设计,统一走 PGPASSWORD + -h 127.0.0.1(md5 通道),实测稳定。
坑 2:pg_hba_file_rules 视图不存在 —— 产品功能差异
现象:想在线核对运行中实例的 hba 规则(PG 10+ 的标准姿势):
$ vsql -d postgres -p 5432 -c "select * from pg_hba_file_rules;"
错误: 关系 "pg_hba_file_rules" 不存在在 node1
原因:G100 当前内核(报 PostgreSQL 9.2.4 谱系)没有引入该视图。
解决:核对 hba 只能看文件本身 + 实测连接行为,改完记得重载并验证。
坑 3:vsql 对 SQL 错误返回退出码 0 —— 自动化脚本的头号陷阱
现象:授权被收回后 ops_ro 的查询在回显里明明白白报"权限不够",shell 里 $? 却是 0;改密报错"旧密码不能为空"那次同样 exit=0,口令实际没改成功。
排查:一组对照实验钉死退出码行为:
| 场景 | 退出码 |
|---|---|
| 正常 SQL | 0 |
| SQL 报错(不存在的表/权限不够/改密语法错) | 0 |
SQL 报错 + -v ON_ERROR_STOP=1 |
3 |
| 连接失败(实例没起/口令错/账户锁定) | 2 |
原因(定性):产品默认行为,vsql 只把"连接级致命错误"映射为非零退出码,SQL 层错误不影响退出码。
解决:脚本里 vsql 一律加 -v ON_ERROR_STOP=1,或者干脆以回显文本判定成败。不看退出码直接判成功,是 G100 自动化翻车的第一现场。
坑 4:用户本人改密必须带 REPLACE —— 产品语法要求
现象:ALTER USER xxx IDENTIFIED BY '新口令' 不带 REPLACE,报"旧密码不能为空,请用’replace’语法输入旧密码",且 vsql 退出码为 0(叠加坑 3,很容易以为改成功了)。
原因(定性):Oracle 风格改密语法的强制校验:本人改密必须自证旧口令。管理员改密(ALTER USER ... WITH PASSWORD)不需要 REPLACE。
解决:本人改密补上 REPLACE '旧口令';改完立刻用新口令登录验证、旧口令验证被拒,两步都做才算改完。另外口令复用策略会拦"新密码不能和旧密码相同"(reuse_max=3 / reuse_time=90),轮换口令时别想着换回去。
坑 5:默认授权"管理员代设不生效" —— 沿袭 PG 的语义,新手必踩
现象:7.5 节的完整对照:管理员 vastbase 执行 ALTER DEFAULT PRIVILEGES ... GRANT SELECT ON TABLES TO ops_ro,之后 ops_demo 建的新表 relacl 为空,ops_ro 照样"权限不够";换成 ops_demo 本人执行同样语句,新表自动带上授权。
原因:默认授权按执行者记账,只作用于执行者本人将来创建的对象——这与原生 PostgreSQL 语义一致,不算缺陷,但"管理员替业务用户配置默认授权"这个直觉动作必踩。
解决:默认授权由对象属主本人执行;若业务用户做不到,管理脚本里用 ALTER DEFAULT PRIVILEGES FOR ROLE ops_demo ... 显式指定目标角色(本实例未实测该写法,用前自行验证)。
坑 6:手工 vb_ctl 与 systemctl 混用互踩 —— 操作失误 + 单元文件设计
现象:3.4 节全程复盘:vb_ctl 手工拉起后 systemd 视角仍 inactive;此时 systemctl start 不但不报"已在运行",反而触发 ExecStop 把运行中的库停掉,status 里 ExecStart/ExecStop 双双 SUCCESS、服务 inactive(dead);之后再 vb_ctl stop 又报"PID 文件不存在"(exit=1)。
原因:systemd 单元 Type=forking + ExecStop 无条件执行 vb_ctl stop 的设计,叠加"手工启动后 systemctl start"这个操作失误,两股力量互踩。
解决:3.4 节末尾的三条铁律——动手前多源核实(is-active + ss + vb_ctl status);手工起的用手工停;日常只走 systemctl。
坑 7:vsql 没有 -w 选项 —— 产品差异
现象:按 PG 习惯加 -w(永不交互提问)想复现认证失败:
$ vsql -d opsdb -p 5432 -U ops_demo -w -Atc 'select 1;'
vsql: 不适用的选项 -- w
尝试 "vsql --help" 以得到更多资讯。
原因:G100 vsql 裁掉了这个选项。
解决:非交互场景避免触发提问,用 PGPASSWORD 显式传口令(或脚本里重定向 stdin 关闭交互)。
坑 8:启动日志里的 cgroup / gaussdb.version 告警 —— 噪音,勿慌
现象:vb_ctl 启动日志里刷"未能解析 cgroup 配置文件""未能打开特性控制文件 gaussdb.version"等警告。
原因:容器/cgroup 特性与特性控制文件在本机未配置,属启动噪音。
解决:实测这些警告不影响实例启动与服务(启动后 vsql 连通、端口监听正常),确认"服务端进程已经启动"行和端口即可,不用逐条消音。
九、常见问题排错速查
| 现象 | 根因 | 解决 |
|---|---|---|
连接到失败 Unknown:5432. |
实例未启动或端口不对 | systemctl status vastbase-server + ss -lntp | grep 5432 |
vsql: 致命错误: 用户名或密码错误,登录拒绝 |
口令错/口令已被轮换 | 管理员 ALTER USER ... WITH PASSWORD 重置 |
vsql: 致命错误: 账户被锁定 |
连续失败触发锁定(1440 分钟) | 等待超时或管理员 ACCOUNT UNLOCK |
错误: 密码必须包含至少8个字符。 |
口令策略(min_length=8) | 换满足长度的口令 |
错误: 旧密码不能为空,请用'replace'语法输入旧密码。 |
本人改密缺 REPLACE | IDENTIFIED BY '新' REPLACE '旧' |
错误: 新密码不能和旧密码相同 |
口令复用策略(3 次/90 天) | 用没用过的新口令 |
错误: 对关系 xxx 权限不够 |
表级权限缺失 | GRANT 对应表权限 |
错误: 对模式 xxx 权限不够 |
schema USAGE 缺失 | GRANT USAGE ON SCHEMA ... TO ... |
错误: 无法删除"xxx"因为有其它对象依赖它 |
名下还有库/表/视图 | 先删库/移交属主再 DROP USER |
| 脚本里 SQL 明明报错 exit 却是 0 | vsql 退出码行为(坑 3) | 加 -v ON_ERROR_STOP=1 |
systemctl status 显示双 SUCCESS 却 inactive |
vb_ctl/systemd 混用互踩(坑 6) | 核实端口后交回 systemctl start |
十、附录:DBA 日常操作速查
# ---------- 启停 ----------
systemctl start vastbase-server # 启动
systemctl stop vastbase-server # 停库(fast)
systemctl restart vastbase-server # 重启
systemctl is-active vastbase-server # 状态确认(active/inactive)
systemctl is-enabled vastbase-server # 开机自启确认
vb_ctl status -D /backup/vastbase/data # 数据目录视角(root/vastbase 均可看)
vb_ctl start -D /backup/vastbase/data -t 60 # 手工拉起(救场用,见坑6)
vb_ctl stop -D /backup/vastbase/data -m fast -t 60
# ---------- 连接 ----------
su - vastbase # 本机免密(管理员)
vsql -d postgres -p 5432
PGPASSWORD='******' vsql -h 127.0.0.1 -p 5432 -U 业务用户 -d 库名 # md5 通道
# ---------- 用户 ----------
CREATE USER ops_demo WITH PASSWORD '******';
ALTER USER ops_demo WITH PASSWORD '******'; # 管理员改密
ALTER USER ops_demo IDENTIFIED BY '新******' REPLACE '旧******'; # 本人改密
ALTER USER ops_ro ACCOUNT LOCK; / ACCOUNT UNLOCK;
DROP USER ops_tmp; # 先删/移交名下对象
# ---------- 库/schema ----------
CREATE DATABASE opsdb OWNER ops_demo ENCODING 'UTF8';
ALTER DATABASE opsdb OWNER TO ops_demo;
CREATE SCHEMA ops AUTHORIZATION ops_demo;
# ---------- 表/视图/索引 ----------
CREATE TABLE emp (id int PRIMARY KEY, name varchar(50) NOT NULL);
CREATE INDEX idx_emp_dept ON emp(dept);
CREATE VIEW v_emp_high AS SELECT id,name FROM emp WHERE salary>=8000;
DROP INDEX idx_emp_tmp_id; DROP VIEW v_emp_tmp; DROP TABLE emp_tmp;
# ---------- 授权/取消 ----------
REVOKE CONNECT ON DATABASE opsdb FROM PUBLIC;
GRANT CONNECT ON DATABASE opsdb TO ops_ro;
GRANT USAGE ON SCHEMA ops TO ops_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA ops TO ops_ro;
GRANT INSERT,UPDATE ON ops.emp TO ops_ro;
REVOKE INSERT,UPDATE ON ops.emp FROM ops_ro;
-- 默认授权:由属主本人执行(见坑5)
ALTER DEFAULT PRIVILEGES IN SCHEMA ops GRANT SELECT ON TABLES TO ops_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA ops REVOKE SELECT ON TABLES FROM ops_ro;
# ---------- 排查三板斧 ----------
select datname,datacl from pg_database where datname='opsdb';
select nspname,nspacl from pg_namespace where nspname='ops';
select relname,relacl from pg_class where oid='ops.emp'::regclass;
十一、终态快照
演练结束后的机器终态(复核依据):演示库 opsdb 与演示用户 ops_demo/ops_ro 保留在机上,四权账户与 bizdb 未做任何变更。
$ vsql -d postgres -p 5432 -c "select rolname,rolcanlogin from pg_roles where rolname like 'ops%' order by rolname;"
rolname | rolcanlogin
----------+-------------
ops_demo | t
ops_ro | t
(2 行记录)
$ vsql -d opsdb -p 5432 -c "select relname,relkind,relacl from pg_class where relnamespace='ops'::regnamespace and relkind in ('r','v') order by relname;"
relname | relkind | relacl
------------+---------+-----------------------------------------------
dept_dic | r | {ops_demo=arwdDxt/ops_demo,ops_ro=r/ops_demo}
emp | r | {ops_demo=arwdDxt/ops_demo,ops_ro=r/ops_demo}
v_emp_high | v | {ops_demo=arwdDxt/ops_demo}
(3 行记录)
$ vsql -d postgres -p 5432 -Atc 'select pg_postmaster_start_time();'
2026-09-14 09:57:37.807289+08
实例由 systemctl 托管运行中,端口 5432,开机自启 enabled,License 有效期至 2026-12-08。




