openGauss数据库实验全流程:从建库建表到事务备份与JDBC对账

发布时间:2026/10/27 11:49:38
openGauss数据库实验全流程:从建库建表到事务备份与JDBC对账 简介《数据库系统原理实验》报告面向计算机科学与技术、软件工程专业学生及数据库初学者围绕 openGauss 环境下的课程实验整理而成可用于巩固数据库理论、完成实验报告与复习 SQL 操作。压缩包共 1 个 docx 文件约 3.23MB内容按实验一至实验九组织涵盖认识 DBMS、创建数据库表和索引、交互式 SQL、视图、完整性控制、安全性控制、事务与并发控制、备份恢复及 JDBC 连接数据库等主题。文档保留实验目的、内容、步骤、截图要求与结果分析便于读者对照复现操作、理解权限与事务机制、排查常见问题也可作为课程作业和考前梳理的参考。目前已有 1525 人学习适合需要系统练习数据库实验的读者按章节查阅。1. 这份数据库实验报告书真正能复用的是九次实验压出来的命令顺序数据库这门课有个很常见的错位理论卷面能拿高分坐到终端前却连一条带外连接的三表查询都要翻笔记。这份《数据库系统原理实验》报告书针对的正是这个落差——它把九个实验串成一条完整链路装 openGauss、gsql 连上去、建表空间和库、建六张表、建索引、写交互式 SQL、建视图、做完整性与安全性控制、跑事务并发、备份恢复最后从 Java 侧用 JDBC 连回来。它适合两类人正在赶实验报告、需要一个能逐条对照的命令清单的计算机类专业学生以及离开课堂太久、想用开源库把 SQL 手感重新捡回来的开发者。排版模板好抄值钱的是每一步的命令顺序和那些会报错的边界。2. 环境落地从 openGauss 安装到 gsql 连上有三个必过的关口环境这一步最容易出现的问题是装完了却连不上、连上了却找不到库、找到了库却发现自己没权限建表。三个关口分别是机器资源够不够、管理命令有没有在正确的操作系统用户下执行、端口和库名有没有对上。绕过任何一环后面八个实验都得停下来补课。2.1 三种安装路径怎么选先看你手里有什么机器报告里列了三种模式实际操作时选哪条取决于你手上现成的资源而不是哪条看起来最“正规”。安装路径适用条件大致耗时最容易出问题的点云主机镜像部署有可用的云主机、能拿到管理员权限30 分钟到 1 小时安全组没放行数据库端口、镜像自带的初始口令没记录虚拟机一键安装本地有 VMware 或 VirtualBox内存给到 8G 以上1 到 2 小时内存不足导致安装脚本中途退出回滚不干净先装 openEuler 再装 openGauss想顺带练 Linux、磁盘留足 40G 以上3 小时以上依赖包缺失、Python 版本不匹配我一般会建议第一次上手走第二条。一键安装脚本把用户创建、目录初始化、环境变量都替你做了出错时只要把虚拟机快照回滚重来代价可控。云主机那条路看着最快但安全组、内网地址、初始密码三件事只要漏一件你就会在“连接被拒绝”上耗掉一晚上而这类问题对新手来说很难自己定位。还有一条血泪经验安装前把虚拟机内存固定在 8G别用动态分配。安装脚本跑到一半因为宿主机内存回收被杀掉留下的半成品实例比全新环境更难清理——它占着目录和端口重装时会报“目录非空”。2.2 omm 用户、gs_om 与 gsql连接串里每个参数都要能解释openGauss 装完之后管理动作必须在安装时指定的操作系统用户下做报告里叫它 omm。远程登录服务器时你是 root直接敲数据库命令会得到各种“权限不足”“找不到命令”这不是数据库的问题是身份不对。# 切到数据库安装用户后续所有管理命令都在这个身份下执行 su - omm # 先看实例状态再决定要不要启动-t 后面跟 status/start/stop gs_om -t status gs_om -t start # 连接默认库-d 指定库名-p 指定端口-r 打开行编辑上下键能翻历史命令 gsql -d postgres -p 26000 -r这段里每个参数都值得单独说一句。-d postgres里的 postgres 是安装时自动生成的默认库你要新建的 db_school 不在里面得先连上这个库才有资格执行CREATE DATABASE。-p 26000是安装时指定的主节点端口换一台机器、换一次安装都可能不一样忘了就用gs_om -t status --detail查别硬猜。-r是打开行编辑没有它敲错一个字符就得整行重打交互式 SQL 实验里能把你逼疯。gs_om和gs_ctl的区别也常被问。gs_om面向集群负责实例的整体启动、停止、状态查询gs_ctl面向单个实例做 reload、promote 这类更细的操作。日常实验用gs_om足够改完配置文件想让它生效又不重启才需要gs_ctl reload。2.3 元命令和系统表同一件事的两条查询路径gsql 里有两套查法元命令反斜杠开头和查系统表。元命令快适合边做边看系统表全适合把结果写进报告或者拿去做脚本判断。我习惯先用元命令定位问题再用系统表拿准确值。想看什么元命令等价的系统表查询有哪些库\lSELECT datname FROM pg_database;当前库有哪些表\dtSELECT tablename FROM pg_tables;表结构\d tablename查 pg_attribute、pg_type表的完整属性\d tablename同上附带存储与压缩信息有哪些 schema\dnSELECT nspname FROM pg_namespace;有哪些索引\diSELECT indexname FROM pg_indexes;有哪些表空间\dbSELECT spcname FROM pg_tablespace;有哪些用户\duSELECT * FROM pg_user;有哪些角色\dgSELECT * FROM pg_roles;pg_user和pg_roles这两张表的关系正好对应实验里那个辨析点用户是具体账户角色是权限集合。pg_user里能看到登录账户pg_roles里能看到包括rolcanlogin标志在内的全部角色把某个角色授予某用户之后用户就继承了这批权限不必逐条 GRANT。这条设计在后面安全性控制实验里会反复用到。3. 建库建表建索引六张表的创建顺序决定你能不能少改三次表实验二看着最枯燥实际上是整门课的地基。库、schema、表、索引这四层东西有严格的从属关系顺序错了后面所有实验都在一个歪掉的结构上跑。最常见的问题是表建完了才发现外键互相引用只能删表重来——而这个代价本来完全可以用一个ALTER TABLE避免。3.1 表空间、数据库、schema三级容器不能跳着装报告里用文件夹做类比表空间相当于磁盘上的一块预留区域数据库是这块区域里划分出的逻辑单元schema 是库内部的名字空间。这个类比基本准确只是要补一句数据库在逻辑上独立跨库查询在 openGauss 里做不了所以建库时要想清楚。-- 1. 表空间LOCATION 指向的必须是已经存在且为空的目录 CREATE TABLESPACE tpcds_local RELATIVE LOCATION tablespace/tablespace_1; -- 2. 建库时直接指定默认表空间避免以后 ALTER 迁移 CREATE DATABASE db_sc WITH TABLESPACE tpcds_local; -- 3. 库改名不能在被改名的库上执行先切回 postgres ALTER DATABASE db_sc RENAME TO db_school; -- 4. 切库 \c db_schoolRELATIVE LOCATION是相对数据目录的路径写成绝对路径会直接报错目录非空同样会失败所以建目录之后别再往里放东西。第三步改名有个隐藏前提当前会话不能连在 db_sc 上否则 openGauss 会提示有活动连接。这不是 bug是防止你在改名的同时还有会话往里写数据。schema 这条线报告里给的例子是CREATE SCHEMA book_eg;然后CREATE TABLE book_eg.Teachers(...)。这一步的意义在于隔离不同 schema 下可以有同名表多用户环境下每个人建自己的 schema表名就不会打架。删的时候用DROP SCHEMA book_eg CASCADE;CASCADE 会把 schema 里的表、视图一起删掉敲之前先\dn看一眼里面有什么。3.2 六张表的创建顺序循环外键必须拆成两步Teachers、Departments、Students、Courses、SC、Teaches 这六张表里藏着一个循环引用Teachers 的 Dno 指向 DepartmentsDepartments 的 Dheadno 又指回 Teachers。谁先建都得引用一个还不存在的表。处理办法是拆成两步先建 Teachers 但不带指向 Departments 的外键再建 Departments 并带上指向 Teachers 的外键最后ALTER TABLE回补 Teachers 那一边。这是整个实验二里唯一必须打乱顺序的地方记住这一点后面五张表就是按依赖关系顺排。-- 第一步Teachers 先建Dno 只留列不加外键 CREATE TABLE Teachers ( Tno CHAR(20) PRIMARY KEY, Tname CHAR(20) NOT NULL, Sex CHAR(20) CHECK (Sex IN (男,女)), Birthday DATE, Title CHAR(20), Dno CHAR(20) ); -- 第二步Departments 引用 Teachers外键写成表级约束并起名 CREATE TABLE Departments ( Dno CHAR(20) PRIMARY KEY, Dname CHAR(20), Dheadno CHAR(20), CONSTRAINT fk_dept_head FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno) ); -- 第三步回补 Teachers 的外键 ALTER TABLE Teachers ADD CONSTRAINT fk_teacher_dept FOREIGN KEY (Dno) REFERENCES Departments(Dno);给约束起名fk_dept_head不是为了好看。后面插入违规数据时报错信息里会带上约束名你一眼就知道是哪条规则挡住的不起名的话报错只给一个系统生成的编号六张表的外键混在一起排查起来很痛苦。剩下三张表按依赖顺序排列Students 依赖 DepartmentsCourses 独立SC 依赖 Students 和 CoursesTeaches 依赖 Teachers 和 Courses。CREATE TABLE Students ( Sno CHAR(20) PRIMARY KEY, Sname CHAR(20) NOT NULL, Sex CHAR(20) CHECK (Sex IN (男,女)), Birthday DATE, Enrollyear CHAR(20), Speciality CHAR(20), Dno CHAR(20), FOREIGN KEY (Dno) REFERENCES Departments(Dno) ); CREATE TABLE Courses ( Cno CHAR(20) PRIMARY KEY, Cname CHAR(20) NOT NULL, Period SMALLINT, Credit SMALLINT ); CREATE TABLE SC ( Sno CHAR(20), Cno CHAR(20), Grade NUMERIC(5,1), PRIMARY KEY (Sno, Cno), FOREIGN KEY (Sno) REFERENCES Students(Sno), FOREIGN KEY (Cno) REFERENCES Courses(Cno) );Courses 里的 Period 和 Credit 用 SMALLINT 是合理的报告里那段关于取值范围的辨析说的就是这个学时和学分不可能超过 32767用 INT 是浪费空间。真正要注意的是 SC 的主键——PRIMARY KEY (Sno, Cno)是复合主键它同时保证了“一个学生一门课只能有一条选课记录”这条约束在插入重复数据时会直接拦住你。建完之后用\dt确认六张表都在再逐个\d tablename把表结构截图进报告。这一步别省报告要求截图下方带编号和图题早截比事后补好。3.3 列级约束与表级约束怎么分报告里花了不少篇幅讲这两者的区别落到实操只有三条判断标准。位置不同列级约束写在列定义后面用空格分隔表级约束写在所有列定义之后用逗号分隔。能力不同涉及多个列的约束比如复合主键、复合外键只能写成表级非空和默认值这类只作用于单列的写成表级反而不被支持。可读性不同表级约束可以起名列级不行。一个具体的取舍Students 表里的CHECK (Sex IN (男,女))写成列级完全够用因为它只约束一列。但如果你还想加一条“入学年份不能晚于出生年份加 30 年”这种跨列规则就必须升级成表级约束。我在带实验时见过有人在列级里硬塞跨列 CHECK语法上过不去浪费半小时。3.4 索引建在哪一列用 \di 和执行计划验证索引这一节最容易走过场照着CREATE INDEX Student_Dept ON Students(Dno);敲一遍看到\di里有输出就算完成。但实验报告要求写“结果分析”你得说清楚这条索引为什么建在 Dno 上。原因在查询模式学生按院系筛选是最常见的过滤条件WHERE Dno D01这种等值查询如果没索引就得全表扫描。Dno 是外键列选择性谈不上高一个院系下可能有几百个学生但比起全表扫仍然是数量级的差距。-- 在学生表的外键列上建索引 CREATE INDEX Student_Dept ON Students(Dno); -- 确认索引已创建注意主键会自动生成一个同名索引这里应该看到两条 \di -- 用执行计划验证有索引时应出现 Index Scan 而不是 Seq Scan EXPLAIN SELECT * FROM Students WHERE Dno D01;\di列出来的索引会比手工建的多这是正常的——DBMS 会为主键自动建索引那条不是你写的但同样占空间、同样影响写入性能。这一点在报告的分析部分值得写一句索引不是越多越好每多一条索引INSERT 和 UPDATE 就多一份维护开销。EXPLAIN的输出要会看关键字段扫描方式Seq Scan / Index Scan、预估行数、执行代价。数据量只有几十行时优化器很可能仍然选全表扫描因为走索引的代价反而更高。这时候别怀疑索引没生效插几百行测试数据再看一次就正常了。4. 交互式 SQL 与视图查询跑不出来时按四步往下拆实验三到实验七是四个实验但它们共享同一套调试方法先确认表里有没有数据再确认连接条件写没写对然后确认过滤条件放在 WHERE 还是 HAVING最后才看 SELECT 列有没有算错。顺序颠倒过来你会在一个空结果集上反复改列名。4.1 多表连接先把结果集缩小再 JOIN三表连接的写法有几种结果一样可读性差很多。报告里的例子是学生、课程、成绩三张表我一般建议按“主表 → 关联表 → 关联表”的顺序写把过滤条件尽量往前放。-- 查成绩 80 分以上的学生姓名、课程名和分数 SELECT s.Sname, c.Cname, sc.Grade FROM Students s JOIN SC sc ON s.Sno sc.Sno JOIN Courses c ON sc.Cno c.Cno WHERE sc.Grade 80 ORDER BY sc.Grade DESC;逻辑上SQL 的执行顺序和书写顺序不一致先 FROM 确定数据源再 ON 做连接匹配然后 WHERE 过滤接着 GROUP BY 分组、HAVING 过滤组之后才是 SELECT 取列和 ORDER BY 排序。理解这个顺序你就能解释为什么 WHERE 里不能写聚合函数——那时候还没分组。参数上要注意的是别名。Students s这种短别名在单表查询里可有可无三表以上就是刚需否则每列都得写全表名一行 SQL 能拉到屏幕外。结果不对时的排查路径先把 JOIN 换成单表SELECT count(*)确认每张表都有数据再把 WHERE 去掉看连接本身是否正确行数应该是各表匹配数的乘积量级最后把 SELECT 的列逐个加上看哪一列开始出问题。4.2 聚合与分组WHERE 和 HAVING 的分界线分组查询的典型错误是把聚合条件写进 WHERE。-- 统计每个学生的平均分没有选课的学生不参与统计 SELECT s.Sno, s.Sname, AVG(sc.Grade) AS avg_grade FROM Students s JOIN SC sc ON s.Sno sc.Sno GROUP BY s.Sno, s.Sname HAVING AVG(sc.Grade) 60 ORDER BY avg_grade DESC;HAVING AVG(sc.Grade) 60里的聚合函数只能出现在 HAVING不能出现在 WHERE。原因是 WHERE 在分组之前执行那时候 AVG 还没算出来。这条规则几乎所有教材都写但真正写错的人不少因为顺序颠倒时数据库报的错很含糊只说“聚合函数不能出现在此处”。GROUP BY 后面列了 Sno 和 Sname 两列这是必须的SELECT 里出现的非聚合列都要出现在 GROUP BY 里除非该列函数依赖于分组键。Sno 是主键理论上只写 Sno 就够但很多实现不认函数依赖写全更保险。想把“没选课的学生”也算进去就得把内连接换成左外连接同时把过滤条件从 WHERE 挪到 ON 里否则左连接会被 WHERE 退化成内连接——这是外连接最经典的翻车点也是实验三和实验四之间最值得对照的一次改写。4.3 视图把复杂查询固化也把依赖固化视图在报告里是实验四的独立内容实际用起来它就是给一段查询起了个名字。-- 把学生和院系的连接固化成视图 CREATE VIEW v_student_dept AS SELECT s.Sno, s.Sname, d.Dname FROM Students s JOIN Departments d ON s.Dno d.Dno; -- 查视图的定义和列属性 \d v_student_dept -- 像查表一样查视图 SELECT * FROM v_student_dept WHERE Dname 计算机系;视图带来两件事。好事是复杂查询不用每次重写权限也好控制——你可以只把视图的 SELECT 权限给某个用户让他看不到基表的其他列。麻烦事是依赖被固化了基表改名、删列、改类型视图会一起失效而且报错时机是查询视图的那一刻不是改基表的那一刻。我一般会提醒一句视图上做更新要格外小心。简单视图单表、无聚合、无 DISTINCT通常可更新多表连接的视图基本不可更新硬写 UPDATE 会报错。实验报告里如果要写这部分把“不可更新的原因”讲清楚比贴一条报错更有价值。4.4 完整性与安全性约束和权限分别在哪一层生效实验五和实验六解决的是两个不同层面的问题。完整性管的是“数据本身对不对”安全性管的是“谁能碰这些数据”。两者都靠 DDL 语句配置但生效时机完全不同。完整性这一层四类约束各有分工NOT NULL 挡住空值CHECK 挡住不合法的值域PRIMARY KEY 挡住重复和空值FOREIGN KEY 挡住引用不存在的记录。加约束用 ALTER TABLE注意已有数据不满足新约束时会直接失败。-- 给入学年份加一条值域约束注意已有数据必须先合规 ALTER TABLE Students ADD CONSTRAINT ck_enrollyear CHECK (Enrollyear BETWEEN 2000 AND 2030); -- 故意插一条违规数据验证约束确实生效应该报错 INSERT INTO Students (Sno, Sname, Sex, Enrollyear) VALUES (S999, 测试, 男, 1990);第二条 INSERT 报错是预期行为把报错信息截图放进报告这就是“约束生效”的证据。如果它没报错说明约束没建上回去用\d Students看看约束列表里有没有 ck_enrollyear。安全性这一层颗粒度是对象加操作。逐条 GRANT 能让权限最小化但用户一多就难维护所以更好的做法是先建角色再把角色授予用户。-- 建一个只读角色把查询权限挂到角色上 CREATE ROLE role_reader; GRANT SELECT ON Students, Courses TO role_reader; -- 建用户并把角色授予他 CREATE USER u_query IDENTIFIED YourPass2024; GRANT role_reader TO u_query; -- 收回课程表的查询权限验证 REVOKE 的传递效果 REVOKE SELECT ON Courses FROM role_reader;第三步的 REVOKE 有个容易忽略的点从角色上收回权限所有被授予该角色的用户会同时失去这个权限。这正是角色存在的意义——权限变更只在一个地方发生。密码要满足复杂度要求太简单的口令在建用户那一步就会被拒绝报错信息里会写清楚规则照着改就行。4.5 事务与并发两个 gsql 会话手动复现实验七讲事务光看定义没用得亲手制造一次锁等待。开两个终端都连同一个库。-- 会话 A开启事务并更新先不提交 BEGIN; UPDATE Courses SET Credit Credit 1 WHERE Cno C01; -- 停在这里不要 COMMIT-- 会话 B先读再试着改同一行 SELECT * FROM Courses WHERE Cno C01; -- 能读读到的是旧值 UPDATE Courses SET Credit 0 WHERE Cno C01; -- 这里会卡住会话 B 的 UPDATE 会一直挂着直到 A 执行 COMMIT 或 ROLLBACK。这个现象就是行级锁A 没提交前那一行的写锁在它手上。B 的 SELECT 能读到旧值说明默认的 READ COMMITTED 隔离级别下读不阻塞写、写阻塞写。验证完记得把 A 的事务结束掉ROLLBACK比COMMIT更安全——回滚能把你刚才的改动撤掉避免测试数据污染后续实验。再补一组对比把隔离级别提到 SERIALIZABLE重新跑一遍上面的流程你会发现 B 的 SELECT 都可能被阻塞或者报序列化冲突。这个对比写进报告比单纯抄定义有说服力得多。5. 避坑与排查九个实验里最容易翻车的五处这一节列的五条都是我在跟着这份报告走完整流程时真实撞过的每条按“现象 → 原因 → 解决”写遇到了直接对号入座。5.1 连接层本机连得上远程连不上现象在数据库服务器上用 gsql 一切正常换到 Windows 客户端或者另一台虚拟机报FATAL: Forbid remote connection或者连接直接被拒绝。原因openGauss 安装后默认的监听配置和客户端认证文件只放行了本机连接远程访问需要在pg_hba.conf里显式加一条 host 规则同时确认postgresql.conf里监听地址不是只绑了回环。解决找到实例的数据目录编辑pg_hba.conf加一行类似host all all 192.168.0.0/24 sha256然后用gs_ctl reload让配置生效不用重启实例。改完先用gsql -h 服务器IP -p 26000 -d postgres -U 用户名测一次通了再做后续实验。5.2 对象可见性表明明建了\dt里却没有现象建表语句没报错切到另一个会话\dt看不到或者SELECT时报“表不存在”。原因两个可能。一是建表时带了 schema 前缀表的全名是book_eg.teachers不在当前 search_path 里二是大小写——不加双引号的标识符会被折叠成小写CREATE TABLE Teachers实际存的是 teachers你写SELECT * FROM Teachers能匹配上但写Teachers就匹配不上了。解决先\dn看有哪些 schema再\d schema名.表名确认对象是否存在最后用SHOW search_path;看当前会话的搜索路径。要长期省事就在建表前SET search_path TO book_eg, public;让后续语句默认落在这个 schema 下。5.3 外键插入顺序单条插入都对批量灌数据就报错现象手工一条条 INSERT 没任何问题用脚本批量灌数据时中途报violates foreign key constraint。原因外键要求被引用的记录先存在。批量插入时如果按表的字母顺序或者文件里的书写顺序灌子表可能先于父表写入第一条就撞上外键。解决按依赖拓扑序灌数据——先 Teachers再 Departments然后回补 Teachers 的 Dno接着 Students、Courses最后 SC 和 Teaches。删除时反过来先删子表再删父表或者用ON DELETE CASCADE让数据库自己处理。灌数据前先TRUNCATE所有表并按逆序清空能避免上一轮残留数据干扰。5.4 字符类型CHAR 定长补空格比较和拼接都出意外现象Sex列定义成CHAR(20)存进去的是“男”SELECT LENGTH(Sex)返回 20字符串拼接出来后面拖一串空格和另一个表关联时偶尔匹配不上。原因CHAR 是定长类型长度不足会用空格补齐到声明长度。比较时多数实现会自动去掉尾部空格但LENGTH、字符串拼接、LIKE这些操作不会。解决性别、姓名、专业这类长度不固定的字段直接用VARCHAR(20)别用 CHAR。已经建好的表用ALTER TABLE ... ALTER COLUMN ... TYPE VARCHAR(20)改改之前确认表里没数据或者数据都合规。这条经验在真实项目里同样成立——CHAR 只在长度严格固定的场景比如定长编码才值得用。5.5 并发测试UPDATE 卡住不返回以为数据库挂了现象按 4.5 节的步骤做并发实验会话 B 的 UPDATE 一直停在那里等了几分钟也没动静CtrlC 都退不出来。原因这不是死机是行锁等待。会话 A 的事务没提交那一行的写锁还握在它手上B 只能排队。如果 A 的终端被你关掉了但事务没结束这个锁会一直挂着。解决另开一个会话查SELECT pid, state, query FROM pg_stat_activity WHERE state ! idle;找到阻塞的会话确认之后再决定是让它 COMMIT 还是直接 terminate。做这类实验养成习惯每个 BEGIN 后面都想好什么时候结束它测试完立刻 ROLLBACK别把未提交事务留在那里过夜。6. 备份恢复与 JDBC 对账把“能跑通”变成“能验证”实验八和实验九最容易做成形式主义备份命令跑完看到文件生成了就交差JDBC 打印一句“连接成功”就截图。这两步真正要验证的东西是数据在离开原库之后还能不能被还原、还能不能被另一个程序读到。我一般用“三方对账”来收尾原库行数、恢复库行数、JDBC 查出来的行数三个数必须一致。# 逻辑备份整库导出成一个可读的 SQL 文本 gs_dump -U omm -W 口令 -p 26000 -f /home/omm/backup/db_school.sql db_school # 恢复到新库先建空库再灌脚本 gsql -d postgres -p 26000 -c CREATE DATABASE db_school_bak; gsql -d db_school_bak -p 26000 -f /home/omm/backup/db_school.sql # 对账第一步两张表的行数必须相同 gsql -d db_school -p 26000 -c SELECT count(*) FROM Students; gsql -d db_school_bak -p 26000 -c SELECT count(*) FROM Students;gs_dump导的是逻辑结构加数据文本可读、可跨版本迁移缺点是库大了之后慢。物理备份gs_basebackup快得多但只能恢复到同版本同架构的实例上做实验用逻辑备份就够。备份方式产出物恢复粒度适用场景gs_dump文本 SQL 或自定义格式库、schema、表迁移、单表找回、留档gs_basebackup数据目录的物理副本整个实例灾难恢复、主备搭建JDBC 那一步对账的意义比“连接成功”大得多。连上之后执行一条SELECT count(*) FROM Students把结果和上面两个数比对三个数对齐才算这条链路真的通了。// openGauss 走 PostgreSQL 协议用配套驱动别随手抓一个旧版 pg 驱动 Class.forName(org.opengauss.Driver); String url jdbc:postgresql://192.168.0.10:26000/db_school; try (Connection conn DriverManager.getConnection(url, u_query, YourPass2024); Statement st conn.createStatement(); ResultSet rs st.executeQuery(SELECT count(*) FROM Students)) { rs.next(); System.out.println(JDBC 侧行数: rs.getInt(1)); // 必须和原库一致 }这里的坑集中在驱动和认证方式上openGauss 默认的密码加密算法和老版本 PostgreSQL 驱动不匹配用错驱动会在认证阶段报“Invalid username/password”看起来像密码错了其实换驱动就好。另外 URL 里的端口是 26000不是 PostgreSQL 惯用的 5432抄示例代码时最容易漏改这一处。这份报告书我前后翻过三遍每次都是从“建库”那一节开始逐条敲。后来形成一个习惯不管多小的实验只要涉及数据搬迁或者跨程序访问收尾必须走一遍三方对账——原库、恢复库、客户端三个数对不上就说明中间某一步被跳过了绝不靠“看起来成功了”过关。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询