简介:《VASTDATA Vastbase G100 V2.2用户手册》面向国产化数据库初学者、开发与运维人员,服务于信创数据库选型了解、日常操作查询和基础使用学习。手册围绕 Vastbase G100 的整体概况展开,先介绍数据库逻辑结构图、数据查询请求处理过程、管理事务与相关概念,再延伸到连接数据库、配置服务端远程连接、使用 vsql 和应用程序接口、关闭数据库、创建和管理数据库、规划存储模型及表空间等操作,目录层级清楚,适合按模块检索,也便于快速建立 Vastbase G100 的使用框架。压缩包仅含 1 个 PDF 文件,大小约 8.76MB,便于离线保存与随查随用;文中还提醒 OCR 扫描可能存在个别字识别误差,阅读时需结合上下文理解。已有 199 人学习,可作为梳理国产数据库基础概念、熟悉常用操作路径和排查入门问题的参考资料。
1. 拿到 Vastbase G100 V2.2 手册先别急着翻目录:三类人能在里面找到什么
信创数据库这四个字,很多人是在选型会上第一次听到的,真正落到手里,第一件事是找一份能照着敲的手册。Vastbase G100 V2.2 的用户手册就是这种定位的东西:它不讲故事,讲的是一个基于 openGauss 路线演进的关系型数据库,从逻辑结构、连接方式、建表建分区,一路写到 JDBC/ODBC 接口和 SSL 认证。放进一套完整的数据库解决方案里,它承担的是“底座怎么连、对象怎么建、权限怎么管”的那部分。适合两类人:一类是刚接手这套 vastbase 数据库、要在一周内把环境和业务跑通的开发;另一类是 DBA,拿它当参数和权限策略的对照表。手册里那些目录层级,其实就是排错时的检索路径。
2. 从逻辑结构到查询链路:前两章先建立三个模型
很多人拿到 PDF 直接跳到第 3 章“从这里开始”,结果敲到第五行就卡住,因为不知道该在哪个库里建 schema、不知道该用哪个用户连。前两章看着像背景铺垫,实际是把后面所有操作的坐标系先定下来。这三个模型没建立起来,后面每一条命令都是盲敲:库和实例的边界在哪、一条 SQL 进来之后被谁处理、事务的提交点落在哪。
2.1 逻辑结构图决定了你的对象命名习惯
手册 2.1 给的逻辑结构,本质是一条自上而下的包含链:数据库实例 → 数据库(Database)→ 模式(Schema)→ 表/索引/视图/序列 → 表空间(Tablespace)。这条链里有两个容易混的边界,值得提前说清楚。
第一个边界是实例与数据库。一个实例下可以挂多个数据库,库与库之间默认不互通,跨库访问要走外部表或者应用层拼装。所以规划阶段就要决定:是按业务线分库,还是单库多 schema。我一般建议单库多 schema,理由是连接串只改一个参数就能切环境,备份和权限也能按 schema 粒度收敛。
第二个边界是 schema 与用户。这套库的默认行为是:用户创建后拥有一个同名 schema,search_path默认指向它。这就意味着如果你用 A 用户建了表,再用 B 用户去查,不写全限定名就会报“表不存在”。这不是 bug,是权限和路径共同作用的结果。
-- 建库时显式指定编码与兼容模式,避免后期迁移时字符集返工 CREATE DATABASE appdb WITH ENCODING = 'UTF8' DBCOMPATIBILITY = 'A' TEMPLATE = template0; -- 建独立 schema,不要图省事全塞进 public CREATE SCHEMA app_core; -- 把新 schema 放到搜索路径最前面,只对当前会话生效 SET search_path TO app_core, public;DBCOMPATIBILITY是这套库比较关键的一个参数,取值决定了对其他数据库语法的兼容程度,A 通常对应 Oracle 风格、B 对应 MySQL 风格,具体取值手册 3.4 有完整列表。建库之后再改这个参数代价很大,属于典型的“后悔药没处买”的选项,务必在第一次建库时定死。TEMPLATE = template0的作用是拿一个干净模板起库,避免把模板库里的对象带进来。
SET search_path只影响当前会话,断开重连就失效。要长期生效得用ALTER DATABASE appdb SET search_path TO app_core, public;,或者写进用户的属性里。这一点在排查“为什么我这边能查到、同事那边查不到”时非常有用——大概率就是两个人的 search_path 不一样。
2.2 一条查询请求进来之后经过了哪几层
手册 2.2 描述的数据查询请求处理过程,是后面所有性能问题的解释框架。简化成一条链:客户端发起连接 → 监听进程接受并做认证 → 分配服务线程 → 语法解析 → 查询重写 → 优化器生成执行计划 → 执行器拉取数据 → 存储层读写。
这条链上每一环都有对应的可观测点,记住它们比记住参数名更有用:
| 环节 | 出问题时的典型表现 | 先看什么 |
|---|---|---|
| 连接与认证 | 连接超时、认证失败 | 监听地址、认证配置文件、防火墙 |
| 解析与重写 | 语法报错、对象找不到 | search_path、对象是否存在 |
| 优化器 | 计划走错、全表扫描 | 统计信息是否新鲜、执行计划 |
| 执行器 | 内存溢出、临时文件暴涨 | work_mem 类参数、排序量 |
| 存储层 | IO 打满、写入放大 | 行存/列存选型、压缩比 |
优化器那一环是最容易被误判的。同一张表,统计信息刚收集完和长期没收集,执行计划可能从索引扫描变成顺序扫描,差出几十倍。所以碰到“昨天还快、今天突然慢”,第一反应不该是改参数,而是看统计信息是不是过期了。这套库里有自动收集机制,但批量导入大量数据之后,自动收集往往跟不上,手动跑一次 ANALYZE 是常规操作。
2.3 事务的边界要写在代码里,不能指望默认行为
手册 2.3 讲管理事务,核心是三件事:显式开启、显式提交、异常回滚。默认情况下这套库是自动提交模式,一条 INSERT 发过去就落盘了。这在交互式敲命令时很方便,在批量写入时就是灾难——一万条 INSERT 就是一万次提交,每次提交都要刷日志。
-- 批量写入务必显式包事务,把提交次数压到个位数 BEGIN; INSERT INTO app_core.tb_order (order_id, cust_id, amount) VALUES (1001, 2001, 99.50); INSERT INTO app_core.tb_order (order_id, cust_id, amount) VALUES (1002, 2002, 149.00); -- 中间可以做校验,出错直接 ROLLBACK COMMIT;BEGIN到COMMIT之间的语句构成一个原子单元。要注意的是长事务问题:一个事务开在那里几十分钟不提交,会阻止回收机制清理旧版本数据,表文件只涨不缩。这一条在手册里不会写得很重,但实际运维中是最常见的“磁盘莫名满了”的成因之一。
还有一个细节是保存点。复杂业务里如果只想回滚部分操作,用SAVEPOINT sp1;打点,出错时ROLLBACK TO sp1;,整体事务还能继续。这个用法在批量导入部分失败的场景里很好使,比整批重跑省时间。
3. 连接、建库、建表:把第 3 章拆成四步落地
第 3 章是整本手册最厚的一章,也是最容易读散的一章。它把连接、建库、存储模型、表空间、表、分区、系统表、参数全铺在一起,顺序读会不断被打断。我的建议是按依赖关系重排:先打通连接,再定存储位置,再建对象,最后才是分区和压缩这类优化项。下面这四步就是按这个顺序来的。
3.1 远程连接打不通,先改这三处
默认安装完之后,服务端只监听本地回环地址,认证配置里也只放行了本地连接。想让应用服务器连过来,需要动两个文件加一次重载。
第一步,改监听地址。在数据目录下的postgresql.conf里找到listen_addresses:
# 只监听指定网卡,比写 '*' 安全;多网卡用逗号分隔 listen_addresses = '192.168.10.11,127.0.0.1' # 端口按实际规划填,默认实例端口不要和同机其他实例撞 port = 5432第二步,在pg_hba.conf里加放行条目,注意顺序是从上往下匹配、命中即止:
# TYPE DATABASE USER ADDRESS METHOD host appdb appuser 192.168.10.0/24 sha256 host all all 127.0.0.1/32 trustMETHOD一列决定认证方式,sha256是口令认证的常用取值,trust表示免密——只应该出现在回环地址那一行,放到业务网段上等于开门。ADDRESS支持 CIDR 写法,网段划得越细越好,别图省事写0.0.0.0/0。
第三步,重载配置。这套库提供了vb_ctl工具:
# reload 只重读配置,不断连接;改监听地址这类参数通常 reload 即可 vb_ctl reload -D /data/vastbase/data # 确认进程状态与端口监听 vb_ctl status -D /data/vastbase/data ss -lntp | grep 5432-D指向数据目录,路径要和安装时一致,否则工具会报找不到实例。改完还不通,按这个顺序排查:本机ss看端口有没有起来 → 从客户端telnet看网络层通不通 → 看pg_hba.conf里有没有更靠前的规则先命中了拒绝。第三条是最容易漏的,因为规则是顺序匹配的,前面一条host all all 0.0.0.0/0 reject会把后面的放行全部吃掉。
3.2 用 vsql 建立第一条会话
vsql是这套库自带的命令行客户端,用法和主流数据库的 CLI 类似。连上去之后先做三件事:看版本、看当前库、看当前用户。这三条信息在提工单和查文档时是必备上下文。
# -h 主机 -p 端口 -d 库名 -U 用户名,-W 强制提示输入口令而不是明文写在命令里 vsql -h 192.168.10.11 -p 5432 -d appdb -U appuser -W进入交互界面后:
-- 版本信息决定你能用哪些语法特性,别凭印象写 SELECT version(); -- 确认自己连的是哪个库、哪个用户、search_path 是什么 SELECT current_database(), current_user, current_setting('search_path'); -- 查看连接数,排查“连接池被打满”时第一眼看这个 SELECT count(*) FROM pg_stat_activity;-W这个参数值得单独说。很多脚本里图方便把口令写进命令行,结果是ps -ef一眼就能看到,属于典型的安全隐患。要么用-W交互输入,要么用环境变量配合.pgpass类的凭据文件,权限设成 600。
pg_stat_activity这张系统表在手册 3.9 有说明,它能告诉你每个连接的来源地址、状态、正在执行的语句。线上出现“连接数满了但业务量不大”的情况,八成是有连接泄漏,看这张表里state长时间停留在 idle 的会话来自哪台机器,基本就能定位到是哪个应用没关连接。
关闭数据库有两条路径,手册 3.3 分开写了:SQL 方式和工具方式。日常维护我优先用工具方式,因为可以控制模式——正常关闭会等待现有连接结束,快速关闭直接断开,立即关闭相当于断电,只在万不得已时用。SQL 方式适合写在脚本里由应用侧触发,但权限要收得很紧,普通业务账号不应该有这个能力。
3.3 建库、建表空间、建表的依赖顺序
顺序错了会反复返工:表空间没建就先建表,表会落到默认位置,后期迁过去要重建索引。正确顺序是表空间 → 数据库 → schema → 表。
-- 表空间指向一个独立的挂载点,路径写法按手册 3.7 的相对位置语法 CREATE TABLESPACE tsp_app RELATIVE LOCATION 'tablespace/tsp_app'; -- 建库时指定默认表空间,避免用户忘了指定就落到系统盘 CREATE DATABASE appdb WITH ENCODING = 'UTF8' TABLESPACE = tsp_app; -- 大表单独放一个表空间,方便按盘做备份和限流 CREATE TABLESPACE tsp_big RELATIVE LOCATION 'tablespace/tsp_big';RELATIVE LOCATION是相对数据目录的路径,这一点和直接用绝对路径的数据库不一样,容易踩。手册 3.7 明确给了这个语法,但很多人按其他数据库的习惯写绝对路径,直接报错。
表空间的现实价值在于 IO 隔离和备份粒度。把写入量大的日志表和读多写少的维表分到不同表空间,落到不同物理盘上,互相不抢 IO。备份的时候也能按表空间分批做,手册 3.11.7 专门讲了表空间级别的备份与恢复。
建表这一步,除了常规的字段和约束,最需要提前决策的是存储模型。
3.4 行存、列存与压缩:选型错了后面全是补丁
手册 3.5 规划存储模型、3.6 列存下的数据压缩,这两节要连起来看。行存适合 OLTP:按行读取,单条增删改代价小,点查快。列存适合 OLAP:按列读取,聚合扫描只读需要的列,压缩比高,但单条更新代价大。
-- 明细流水表,写入密集、点查多,用行存 CREATE TABLE app_core.tb_order ( order_id bigint NOT NULL, cust_id bigint NOT NULL, amount numeric(12,2), create_time timestamp DEFAULT now(), CONSTRAINT pk_tb_order PRIMARY KEY (order_id) ) WITH (ORIENTATION = ROW, STORAGE_TYPE = USTORE); -- 统计分析表,一次写入、反复聚合,用列存并开压缩 CREATE TABLE app_core.tb_order_stat ( stat_date date, cust_id bigint, total_amt numeric(18,2), order_cnt bigint ) WITH (ORIENTATION = COLUMN, COMPRESSION = HIGH);ORIENTATION有两个取值,ROW和COLUMN,建表时定死,后期改要整表重写。COMPRESSION只对列存有意义,HIGH压缩比更高但写入 CPU 开销更大,日志类冷数据可以开到高档位,需要频繁扫的热数据用中档更均衡。STORAGE_TYPE = USTORE是行存的存储引擎选项,手册 3.5 有对照表,不同引擎在更新密集场景下表现差别明显。
这里有一条血泪经验:列存表不要用来做单条 INSERT 的业务表。列存的写放大在批量场景下才摊得平,一条一条插进去,性能会比行存差一个数量级,而且会产生大量小文件。如果业务确实需要“明细行存 + 分析列存”,标准做法是行存承接交易,定时把数据批量灌进列存做分析,两套表各司其职。
3.5 分区表与 default 分区:边界值是最容易错的地方
手册 3.8.8 讲分区表,3.8.8.1 特别提到支持 default 分区。分区表的价值在于两件事:查询裁剪和分区级维护。前者让优化器只扫相关分区,后者让删历史数据变成 DROP PARTITION 而不是 DELETE。
-- 按月做范围分区,最后一个分区兜底,防止新数据插不进去 CREATE TABLE app_core.tb_log ( log_id bigint, log_date date NOT NULL, content text ) PARTITION BY RANGE (log_date) ( PARTITION p_202401 VALUES LESS THAN ('2024-02-01'), PARTITION p_202402 VALUES LESS THAN ('2024-03-01'), PARTITION p_default VALUES LESS THAN (MAXVALUE) );VALUES LESS THAN是开区间,不含右端点。LESS THAN ('2024-02-01')表示所有小于 2 月 1 日的日期,2 月 1 日当天会落到下一个分区。这个语义错一次,整月的报表数据就会错位,而且因为不报错,很难发现。
MAXVALUE兜底分区是保命的。没有它,超出范围的插入会直接报错,业务侧半夜告警。但如果加了兜底分区却不做数据搬移,时间一长兜底分区会变成最大的那一个,查询裁剪形同虚设。常规做法是留一个定时任务,定期检查兜底分区里有没有数据,有就 ALTER TABLE 拆分出新区间并把数据迁过去。
4. 应用侧接入:JDBC、ODBC、libpq 三条链路的参数怎么写
手册第 4 章占了很大篇幅,JDBC、ODBC、libpq 三条链路分开写,很多内容是重复的——连接、执行、游标、大数据类型,三条链路各写一遍。读的时候可以只精读一条,另外两条对照差异点。这一节按“选哪条、怎么配、哪里会卡”的顺序展开。
4.1 选型:先看你的运行时在哪一侧
Java 应用走 JDBC,这是主流。C/C++ 或者需要嵌到已有 native 进程里的走 libpq,它是最薄的一层,没有额外依赖。ODBC 更多出现在 BI 工具、报表平台、以及一些历史系统里,链路最长,配置项也最多。
三条链路的共性是都要解决四件事:驱动放在哪、连接串怎么写、认证怎么过、结果集怎么取。差异在于前三件事的具体形态。JDBC 靠 jar 包和 classpath,ODBC 靠驱动管理器加数据源配置,libpq 靠动态库加连接字符串。
手册 4.2.2 专门讲了 JDBC 与 JDK 的兼容性,这一节不要跳过。不同驱动版本对 JDK 的最低要求不一样,用错了表现是运行时报类找不到或者方法不存在,而不是编译期报错,排查起来很费时间。
4.2 JDBC:类路径、驱动加载与连接串
JDBC 的配置分三步:把驱动 jar 放进类路径、代码里加载驱动类、拼连接串。
# 方式一:应用启动时用 -cp 把驱动带进去,适合独立 jar 部署 java -cp "app.jar:/opt/vastbase/jdbc/vastbase-jdbc.jar" com.example.Main # 方式二:把 jar 丢进 Web 容器或构建工具的依赖目录,由容器统一加载 # 具体目录按容器类型定,放错位置的表现就是 ClassNotFoundException代码侧:
// 驱动类名以手册 4.2.4 示例中的写法为准,不同驱动包版本包名可能有差异 Class.forName("org.vastbase.Driver"); // ssl=true 表示启用加密链路,sslmode 决定是否校验服务端证书 String url = "jdbc:vastbase://192.168.10.11:5432/appdb" + "?ssl=true&sslmode=verify-ca" + "&connectTimeout=10&socketTimeout=60"; Connection conn = DriverManager.getConnection(url, "appuser", "******");sslmode有几个档位,disable不加密、require加密但不校验证书、verify-ca校验证书链、verify-full连主机名一起校验。生产环境至少用verify-ca,只写require相当于防了窃听没防中间人。
connectTimeout和socketTimeout这两个参数建议显式写。默认值在跨机房场景下可能太长,导致故障时连接池里全是挂住的连接。设成 10 秒和 60 秒是个比较稳妥的起点,具体按业务的 RT 上限调。
手册 4.2.9 讲连接池。这里有个常见误区:以为换了连接池就能解决性能问题。实际上连接池解决的是“连接建立开销”,不解决慢 SQL。池子大小也不是越大越好,连接数超过数据库的并发处理能力之后,多出来的连接只是在排队,反而增加上下文切换。经验值是按 CPU 核数的两到四倍来估,再用压测校准。
4.3 游标与结果集:大结果集不要一次拉完
手册 4.2.6.2 专门写了“使用游标获取结果”。这一节的现实意义在于:一次SELECT返回几十万行,驱动默认会把结果全部读进内存,堆直接爆掉。
// 关闭自动提交是游标生效的前提,否则驱动会一次性取完 conn.setAutoCommit(false); Statement stmt = conn.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(1000); ResultSet rs = stmt.executeQuery("SELECT * FROM app_core.tb_log"); while (rs.next()) { // 逐批处理,内存占用稳定在 fetchSize 量级 } conn.commit();setFetchSize(1000)是关键,它告诉驱动每次从服务端取多少行。取太小网络往返次数多,取太大内存压不住,1000 左右是个常用起点。setAutoCommit(false)不能省,自动提交模式下游标会被提前物化,fetchSize形同虚设。
存储过程返回结果集也是同理,手册 4.2.7.1 讲了获取结果集的写法,核心是把CallableStatement的getResultSet()和游标配合用,而不是一次性getObject()。
大数据类型(手册 4.2.8)分二进制和字符串两类,处理方式不同。二进制走流式读写,避免整个 blob 进内存;大字符串要注意字符集转换带来的额外内存放大。
4.4 ODBC 与 libpq:配置链路更长,顺序不能乱
ODBC 的配置步骤比 JDBC 多得多,手册 4.3.2 拆成了六步:装数据库(或客户端)、装 unixODBC、替换客户端驱动、配数据源、配环境变量、测数据源。这六步的顺序不能颠倒,尤其是“替换客户端驱动程序”这一步,本质是把驱动管理器指向这套库自己的.so文件,指错了后面全白搭。
# 数据源配置文件示例,路径按 unixODBC 的实际安装位置 [vastbase_appdb] Description = Vastbase G100 appdb Driver = /opt/vastbase/odbc/lib/vbodbc.so Servername = 192.168.10.11 Port = 5432 Database = appdb Username = appuser Password = ******配完之后必须用isql实测一次,不要跳过这步直接上应用。isql -v vastbase_appdb能连上说明驱动、路径、口令全都对;连不上时它会打印 SQLSTATE 错误码,比应用里报的一行“连接失败”有用得多。
libpq 是最薄的一层,手册 4.4 给了最小示例。它没有驱动管理器,直接链接动态库,连接字符串用 key=value 形式拼:
// 连接字符串里的每一项都对应一个环境变量名,也可以走环境变量 PGconn *conn = PQconnectdb( "host=192.168.10.11 port=5432 dbname=appdb " "user=appuser password=****** connect_timeout=10"); if (PQstatus(conn) != CONNECTION_OK) { // PQerrorMessage 返回的是服务端原文,排错时比自造错误信息有用 fprintf(stderr, "connect failed: %s", PQerrorMessage(conn)); PQfinish(conn); return -1; }PQerrorMessage一定要打出来。很多人包装了一层之后把这条信息丢了,排查时只能看到“连接失败”四个字,等于把黑匣子扔了。
5. 五个高频翻车点排查:从连不上到权限报错
手册是“正确的路径”,实际干活时遇到的多半是路径之外的岔子。下面五条按出现频率排,每条按现象、原因、解决写,能对号入座的基本上十分钟内能收敛。
5.1 远程连接被拒:三处配置任意一处没改都会这样
现象:客户端报连接超时或者“no pg_hba.conf entry for host”。
原因:三种可能。监听地址还是默认的回环地址;认证配置里没有对应的放行条目;服务器防火墙没开端口。还有一种隐蔽的:认证配置里有条目,但被前面一条更宽的规则先命中了。
解决:按顺序验证。本机ss -lntp | grep 端口看监听是否生效,没有就是listen_addresses没改或者没重载;有监听但远端不通,从客户端 telnet 测网络;网络通还报认证错,就看pg_hba.conf的规则顺序,把具体网段的放行条目放到宽规则前面。改完统一vb_ctl reload,不要 restart,避免影响现有连接。
5.2 列存表批量写入慢得离谱
现象:建了列存表,业务按单条 INSERT 往里写,TPS 只有行存表的几分之一,磁盘上还冒出一堆小文件。
原因:列存的写入模型是批式组织,单条写入要反复打开关闭列文件。手册 3.6 讲压缩时提到列存按列组织数据,但没强调写入模式。选型错位是根因。
解决:短期改成攒批写入,每批几千行,用一条多值 INSERT 或者 COPY 导入;中期把表改成行存承接交易,另建列存表做分析;长期在应用层做读写分离。判断标准很简单:如果这张表的写入以单条为主、查询以点查为主,就不该用列存。
5.3 分区表数据全落进兜底分区
现象:分区表建好了,查询还是全表扫,一看执行计划把所有分区都扫了一遍,再看数据,90% 都在p_default里。
原因:两个可能。一是边界值算错,LESS THAN是开区间,日期差一天就会整体错位;二是新分区没提前建,数据全部由兜底分区接住。
解决:先用系统表确认每个分区的实际行数,找出异常大的那个;再核对分区边界定义和业务的时间口径是否一致,尤其是时区问题——存的是 UTC 时间、边界按本地时间写,必然错位。新分区用定时任务提前一个月建,建完把兜底分区里对应区间的数据迁过去。手册 3.8.8 对分区维护有说明,DDL 的操作窗口建议放在业务低峰。
5.4 开启 SSL 后 JDBC 握手失败
现象:不带 ssl 参数能连,加上sslmode=verify-ca就报证书校验失败。
原因:verify-ca要求客户端能验证服务端证书链。客户端信任库(truststore)里没有导入签发服务端证书的根证书,或者证书的 CN/SAN 和连接串里的主机名对不上(用verify-full时尤其明显)。
解决:先确认服务端证书链完整,手册 5.1.3 给了证书生成流程,根证书、服务端证书、私钥三件套要对得上;再把根证书导进客户端的信任库,Java 侧用keytool -importcert,重启应用;最后核对连接串里的主机名,要么写证书里的名字,要么换verify-ca只校验证书链不校验主机名。调试阶段可以临时降到require确认链路本身通不通,但别把这个配置带上线。
5.5 开了三权分立之后管理员“没权限”
现象:原来能建用户、能改配置的账号,开了三权分立之后操作被拒。
原因:手册 5.2.3 讲的三权分立,是把传统的一个超级管理员拆成安全管理、审计管理、数据管理三个角色,各自职责隔离。原来的管理员账号只保留其中一部分权限,这是设计意图,不是缺陷。
解决:先明确当前操作属于哪一类——建用户和授权归安全管理,查审计日志归审计管理,业务对象的增删改归数据管理。然后用对应角色的账号执行,或者由安全管理员给业务账号单独授权。这里不要图省事把权限再合并回去,三权分立一旦关掉,审计链路就断了。
顺带说一个相关的坑:schema 建了但没授权,业务账号查表报“对象不存在”。原因是 search_path 里没这个 schema,或者有 schema 但没 USAGE 权限。手册 5.2.6 讲 schema 权限,GRANT USAGE ON SCHEMA和GRANT SELECT ON TABLE是两步,缺一不可。
6. 把手册当字典查:参数定位、执行计划验证与备份前的最后一道检查
手册 700 多页,从头读到尾不现实,也没必要。真正高效的用法是把它当字典:遇到具体问题时,按目录定位到对应章节,只读那一节。这一章讲三个我反复用的检索路径,以及一个每次上线前都会走的验证动作。
6.1 参数改动的三个来源,优先级别搞反
参数这东西在不同地方设置会有不同的生效范围,优先级从高到低大致是:会话级SET→ 用户级ALTER USER ... SET→ 数据库级ALTER DATABASE ... SET→ 实例级配置文件。会话级最灵活但只影响当前连接,配置文件影响全局但需要重载。
| 作用域 | 命令形式 | 生效时机 | 典型用途 |
|---|---|---|---|
| 会话 | SET param = value; | 立即,仅当前会话 | 临时调大排序内存跑一条大查询 |
| 用户 | ALTER USER u SET param = value; | 该用户下次连接 | 给批处理账号单独放宽资源 |
| 数据库 | ALTER DATABASE d SET param = value; | 该库下次连接 | 按库隔离资源配额 |
| 实例 | 编辑配置文件 + reload | reload 后对新会话生效 | 全局内存、连接数上限 |
排查“参数改了没生效”时,先用SHOW 参数名;看当前会话实际拿到的值,再逐层往上找是谁覆盖了谁。手册 3.10 有参数配置的完整说明,配合系统表能看到每个参数的当前值和来源。
6.2 用执行计划验证假设,而不是靠猜
判断一条 SQL 慢在哪,唯一可靠的办法是看执行计划。习惯是:先看有没有全表扫描,再看扫描的行数和实际返回行数差多少。差得大说明统计信息不准,先 ANALYZE 再看。
-- 只看计划不真正执行,避免在线上跑重查询 EXPLAIN SELECT cust_id, sum(amount) FROM app_core.tb_order WHERE create_time >= '2024-01-01' GROUP BY cust_id; -- 需要真实耗时和实际行数时才加 analyze,线上慎用 EXPLAIN ANALYZE SELECT ...;看计划时重点看三处:扫描方式(顺序扫描还是索引扫描)、估算行数与实际行数的偏差、有没有落到临时文件。第三项出现说明排序或哈希的内存不够,这时候调work_mem才有意义。反过来,如果计划本身就走错了索引,调内存纯属浪费。
6.3 备份表空间之前,先确认这两件事
手册 3.11.6 和 3.11.7 讲了vb_basebackup的 tar 格式备份和表空间备份。表空间备份比整库备份多一层依赖:备份时必须知道每个表空间对应的物理路径,恢复时这些路径要能对上。
# 备份前先把表空间与路径的对应关系导出来,恢复时照这个表建目录 vsql -h 192.168.10.11 -p 5432 -d appdb -U appuser -W \ -c "SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace;" # tar 格式备份,-D 指定目标目录,-t 指定表空间名(按实际工具参数为准) vb_basebackup -D /backup/base_202403 -h 192.168.10.11 -p 5432 -t tsp_app -F t第一件事是路径清单。恢复到另一台机器上,如果只恢复了数据目录没建表空间目录,启动会直接失败。第二件事是备份期间的数据一致性——vb_basebackup依赖 WAL 保证一致性,备份期间不要做删表空间的操作,否则备份出来的清单和实际数据对不上。
我一般的做法是把路径清单和备份文件放在同一个目录,恢复脚本里先读清单建目录再解包。这个习惯来自一次深夜恢复:备份文件在,路径没记,靠翻安装记录猜了半小时。
从那以后我每次做表空间级备份,都把路径清单和备份文件捆在一起,恢复脚本里强制走一遍校验才允许继续。希望帮到你。
本文还有配套的精品资源,点击获取