
简介这份zzu数据库实验报告书面向计算机科学与技术、软件工程专业学生及数据库初学者围绕《数据库系统原理实验》课程提供从理论到实践的完整实验记录可用于课程实验参考、报告撰写对照与openGauss入门练习。压缩包内仅含1个docx文档大小约3.23MB按前言、九个实验和结果分析组织目录清晰便于按实验顺序查阅。内容覆盖认识DBMS系统、创建数据库表与索引、交互式SQL语句、创建视图、完整性控制、安全性控制、事务与并发控制、数据库备份与恢复以及使用JDBC连接数据库等核心环节并记录实验目的、操作过程、遇到的问题及解决思路。已有1527人学习适合需要照着完成实验、梳理SQL操作或补齐数据库实践短板的学习者参考。1. 一份九个实验连成的数据库实操链条解决的是照着视频一步步点却报错的尴尬数据库实验报告这类材料大多数人拿到手第一反应是照着抄一遍交差真正卡人的地方却从来不在报告正文里——环境起不来、gsql敲进去提示找不到命令、表建完了\dt一片空白、权限给了新用户照样查不出数据。这份《数据库系统原理实验》报告书把九个实验按依赖关系串成一条完整链路从 openGauss 安装与gsql连接起步经建库建表建索引、交互式 SQL、视图、完整性控制、安全性控制、事务与并发控制最后落到备份恢复和 JDBC 编程。它适合正在修数据库系统原理课、需要交报告的学生也适合工作几年却没系统摸过国产数据库、想照着把一条完整操作链路走通一遍的开发者。九个实验的排序本身就是依赖链前一个的产物是后一个的输入这个结构比报告里的截图更值得看。2. 环境底座openGauss 装在哪、gsql 怎么连、元命令看什么动手之前先定一件事这台库装在哪里、用什么身份连、连不上时去哪里看日志。这三个问题不解决后面八个实验全是空中楼阁。报告书把第一个实验放在“认识 DBMS 系统”上看起来像凑数实际是把环境变量、安装用户、端口、服务编排这几件事一次性交代清楚后面的实验才有稳定的落脚点。2.1 三种安装路径的取舍为什么我一般选 openEuler 虚拟机手动装报告书里列了三种方式云上镜像、虚拟机一键安装、先装 openEuler 再装 openGauss。三者不是新旧关系是三种不同的学习收益。安装方式前置条件适合谁主要坑点云上镜像有云账号、会配安全组只想尽快敲 SQL、不关心系统层端口和安全组要单独放行公网连不上多半卡在这虚拟机一键安装本地有虚拟化环境内存给到 4GB 以上第一次装、希望随时推倒重来镜像架构要和宿主机对上磁盘别给太小openEuler 手动安装会装系统、会配软件源想看清目录结构、安装用户和参数依赖包和内核参数最费时间但学到的最多我一般会选第三种理由很实际一键安装把所有细节都包进脚本里了出问题时你面对的是个黑匣子只能重装。手动装过一遍你会知道二进制在哪个目录、数据目录归谁所有、omm这个用户是怎么来的、环境变量写进了哪个文件。这些认知在实验二建表空间、实验八做备份恢复时会直接变成排错能力——因为gs_dump和gs_restore都要以安装用户身份跑路径也都在安装用户的家目录附近。内存和磁盘这两个参数值得单独说一句。数据库实例启动时要预分配共享内存虚拟机给 2GB 内存经常在启动阶段就被系统 OOM 掉表现是gs_om -t start返回成功但status里节点不是 Normal。磁盘我给的上限经验是根分区至少 40GB因为表空间目录、WAL 日志、备份文件都落在同一块盘上实验八导两份自定义格式备份就可能把 20GB 的盘塞满那时候报的错跟磁盘空间毫无关系纯粹是写入失败。2.2 omm 用户、gs_om 与 gsql连接链路拆开看安装完成后日常操作只有三个命令在循环切用户、起服务、连库。报告书里这几行写得很简略但每一行的失败原因都不一样值得摊开。# 1. 切到数据库安装用户。中间这个横杠不能省省了就不加载目标用户的环境变量 su - omm # 2. 看实例状态--detail 会列出数据节点、端口、数据目录 gs_om -t status --detail # 3. 启动/停止/重启参数分别是 start / stop / restart gs_om -t start # 4. 连接默认库 postgres-d 指定库名-p 指定主节点端口-r 打开命令回显 gsql -d postgres -p 26000 -rsu - omm里的横杠是血泪经验。写成su omm只是切换了用户身份登录 shell 不启动.bashrc里配的GAUSSHOME、PATH、LD_LIBRARY_PATH全都不生效接着敲gsql就会得到command not found。很多人第一反应是“没装上”其实东西都在只是环境没加载。判断方法很简单echo $GAUSSHOME有输出就是环境正常空的就是切错了。gs_om -t status --detail是整个实验里最该记住的排错入口。它的输出里有节点角色、端口号、数据目录路径、实例状态。连不上库的时候按这个顺序排先看 status 里节点是不是 Normal不是就去看$GAUSSLOG/pg_log下最新的日志文件日志里通常直接写明了启动失败的原因节点正常但客户端连不上就核对端口报告书里用的是 26000实际环境如果装的时候改过端口就不是这个数端口对、服务也在还是连不上那就是pg_hba.conf没放行客户端来源地址这个文件改完需要重新加载配置才生效不是重启实例。gsql -d postgres -p 26000 -r里postgres是安装时默认生成的库可以先用它建新库。-r只是打开命令回显方便在报告里贴完整操作记录不影响执行结果。这三个参数吃透实验一的连接部分就不会卡。2.3 元命令与系统表对照别只记命令要知道它查的是哪张表报告书列了一长串反斜杠命令容易背混。我给自己的记法是每条元命令背后都对应一张系统表或视图元命令是给人看的简写系统表是给程序查的正式入口。gsql 元命令背后对应的系统表/视图用来看什么\lpg_database有哪些库、属主是谁、字符编码\c dbname无客户端行为切换当前连接的数据库\dnpg_namespace库内有哪些 schema\dtpg_tables当前搜索路径下的表\d tablenameinformation_schema.columns等字段类型、约束、存储参数、分布列\dipg_indexes索引名、所属表、索引定义\dbpg_tablespace表空间名与物理路径\dupg_roles角色、是否可登录、有无超级权限把这张表记熟排查问题时就不必在元命令之间来回试。举两个最典型的场景建完表\dt看不到直接用SELECT current_schema();看当前搜索路径落在哪个 schema再用\dt *.*把全库的表都列出来表大概率建在了跟用户名同名的 schema 下想知道某个角色到底能不能登录\du里的属性列比猜测靠谱。-- 三条自查语句覆盖“我在哪个库、哪个用户、哪个 schema”这个最常见的困惑 SELECT current_database(), current_user, current_schema(); -- 用系统表核对 \l 与 \db 的输出两者应该完全一致 SELECT datname FROM pg_database; SELECT spcname FROM pg_tablespace; -- 查角色和用户用户是能登录的角色角色是权限集合 SELECT rolname, rolcanlogin, rolsuper FROM pg_roles;这三段查询的价值在于可脚本化。做实验报告时手动敲元命令截图没问题但到了实验六安全性控制要验证权限是否真的生效就得在另一个会话里用 SQL 查pg_roles和系统视图元命令的输出没法直接参与判断。报告书里把“查看数据库用户列表”“查看所有角色”单独列出来用意就在这里。3. 建库建表建索引容器得从外往里建约束得从后往前补实验二的坑集中在顺序上。表空间、数据库、schema、表这四层是嵌套关系建反了就是各种“对象不存在”六张教学表之间存在互相参照照着 ER 图从上往下写 CREATE TABLE写到第三张就会卡住。3.1 表空间、数据库、schema 三层容器别搞反报告书里用“表空间相当于文件夹、数据库是划分出来的存储空间”做类比入门够用但有两个真实约束类比表达不出来一个数据文件只能属于一个表空间一个表空间可以承载多个数据库的多个数据文件表空间的相对路径是相对实例数据目录算的而且那个目录必须提前建好、属主必须是安装用户。-- 表空间的相对路径相对实例数据目录指向的目录要事先存在且属主为 omm CREATE TABLESPACE tpcds_local RELATIVE LOCATION tablespace/tablespace_1; -- 建库时指定默认表空间不写 WITH TABLESPACE 就落到 pg_default CREATE DATABASE db_sc WITH TABLESPACE tpcds_local; -- 改名之后gsql 连接参数和应用连接串里的库名都要同步改 ALTER DATABASE db_sc RENAME TO db_school; -- \c 是 gsql 元命令不是标准 SQL别写进 .sql 脚本里批量执行 \c db_school -- schema 是库内的命名空间和“用户”不是一回事同名只是默认约定 CREATE SCHEMA book_eg;这里最值得记的是\c那一行。它属于客户端元命令写进.sql文件再用gsql -f执行会直接报语法错误。做实验时手动敲没问题等到实验八写恢复脚本、想把“建库 切库 建表”串成一个文件一次跑完就会在这里翻车。正确做法是把切库动作留在命令行脚本里只放纯 SQL。另一个反复出现的困惑是 schema 和 user 的关系。报告书辨析得很清楚物理上的 schema 是库内的名字空间装着一组表、视图、存储过程用户是登录账户角色是权限集合。默认情况下用某个用户建表表会落在与该用户同名的 schema 里所以\dt能看到一旦显式指定了book_eg.Teachers这种带前缀的写法表就进了book_eg当前搜索路径不包含book_eg时\dt自然是空的。这不是没建成是看的地方不对。3.2 六张教学表的 DDL先建列后补参照报告书给出的实体是教师、院系、学生、课程、选课、授课六张表关系里有一处循环参照Teachers的Dno指向DepartmentsDepartments的Dheadno又指回Teachers的Tno。这种结构无论先建哪一张另一张的外键都无处可指。惯常做法是第一遍只建列和单表约束外键留到 3.3 用ALTER TABLE补。-- 第一遍只写列定义、主键、非空、CHECK互相参照的外键全部留空 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) ); CREATE TABLE Departments ( Dno CHAR(20) PRIMARY KEY, Dname CHAR(20), Dheadno CHAR(20) ); 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), -- 表级约束涉及外键时必须写在列定义之后并指明列名 CONSTRAINT fk_student_dept FOREIGN KEY (Dno) REFERENCES Departments(Dno) ); CREATE TABLE Courses ( Cno CHAR(20) PRIMARY KEY, Cname CHAR(20) NOT NULL, Period SMALLINT, -- 学时无符号取值范围 0~65535 Credit SMALLINT -- 学分同样用 SMALLINT 就够 ); CREATE TABLE SC ( Sno CHAR(20), Cno CHAR(20), Grade SMALLINT, CONSTRAINT pk_sc PRIMARY KEY (Sno, Cno), CONSTRAINT fk_sc_student FOREIGN KEY (Sno) REFERENCES Students(Sno), CONSTRAINT fk_sc_course FOREIGN KEY (Cno) REFERENCES Courses(Cno) ); CREATE TABLE Teaches ( Tno CHAR(20), Cno CHAR(20), CONSTRAINT pk_teaches PRIMARY KEY (Tno, Cno), CONSTRAINT fk_teaches_teacher FOREIGN KEY (Tno) REFERENCES Teachers(Tno), CONSTRAINT fk_teaches_course FOREIGN KEY (Cno) REFERENCES Courses(Cno) );几个参数值得单独交代。Sex的约束写成CHECK (Sex IN (男,女))而不是CHECK (Sex男 OR Sex女)两者等价但前者在字段一多时可读性明显更好也更不容易在括号上出错。Period和Credit用SMALLINT是性价比选择2 字节、无符号范围 0 到 65535学科时和学分绰绰有余比一律用INT省空间也更能表达语义。SC和Teaches用的是复合主键因为一个学生可以选多门课、一门课可以被多个学生选只有(Sno, Cno)合起来才唯一。列级约束和表级约束的差别在这里体现得很直接。NOT NULL、单列CHECK、单列主键都能写在列后面属于列级外键因为要指名引用哪张表的哪一列必须写成表级放在所有列定义之后用逗号与列定义隔开。报告书里那段辨析写得绕落到操作上就一句话约束涉及到本表以外的东西就写成表级。3.3 循环参照怎么补外键索引建在哪一列上六张表的壳子建完补外键的顺序反而简单了——因为两张表都已经存在谁先谁后都不会报错。-- 循环参照只能靠 ALTER TABLE 补建表时硬写会互等对方先存在 ALTER TABLE Teachers ADD CONSTRAINT fk_teacher_dept FOREIGN KEY (Dno) REFERENCES Departments(Dno); ALTER TABLE Departments ADD CONSTRAINT fk_dept_head FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno); -- 外键列单独建索引从表做参照完整性检查时不必全表扫描 CREATE INDEX Student_Dept ON Students(Dno); -- 复合索引的列顺序按最左前缀原则定等值条件在前、范围条件在后 CREATE INDEX idx_sc_cno_grade ON SC(Cno, Grade); \diStudent_Dept这个索引是报告书里给出的例子它建在Students.Dno上而这个列正是指向Departments的外键列。为什么要给它建索引因为删除或更新院系表的一行时数据库要确认学生表里没有还在引用它的记录没索引就是全表扫描学生表一旦上万行这个动作会明显变慢。这个因果关系比“索引能加速查询”这种笼统说法有用得多。索引不是越多越好这里有个容易犯的错给主键再手工建一次索引。主键在 openGauss 里会自动创建唯一索引\di里能看到那个系统命名的索引对象再对同一列CREATE INDEX属于重复建设写数据时白白多维护一棵 B 树。真正需要手工建的是外键列、高频过滤条件列、以及经常出现在ORDER BY里的排序列。删除索引用DROP INDEX 索引名;重建之前先\di确认索引名别照着记忆敲。4. 交互式 SQL 到视图、完整性、安全性、并发四个实验其实是一条链实验三到实验七在报告书里是四份独立的实验报告但从操作依赖看它们共用同一套表、同一批数据后者不断在前者搭好的结构上加约束、加权限、加事务边界。拆开看是四个知识点串起来看是一次完整的数据库能力建设。4.1 多表连接、视图创建与视图可更新的边界实验三练的是查询实验四练的是把查询固化下来。多表连接写熟了视图就是给一段固定连接起个名字。-- 四表连接学生、院系、选课、课程过滤出不及格记录 SELECT s.Sno, s.Sname, d.Dname, c.Cname, sc.Grade FROM Students s JOIN Departments d ON s.Dno d.Dno JOIN SC sc ON sc.Sno s.Sno JOIN Courses c ON c.Cno sc.Cno WHERE sc.Grade 60 ORDER BY sc.Grade; -- 视图把连接关系固定下来查询侧只写单表过滤条件 CREATE VIEW v_student_dept AS SELECT s.Sno, s.Sname, s.Speciality, d.Dname FROM Students s JOIN Departments d ON s.Dno d.Dno; -- 带检查选项的视图通过视图写入的行必须满足视图自身的 WHERE 条件 CREATE VIEW v_sc_pass AS SELECT * FROM SC WHERE Grade 60 WITH CHECK OPTION;视图能不能更新是实验四最容易答错的地方。判断依据是视图定义里有没有破坏“一行对一行”映射的结构含聚合函数、DISTINCT、GROUP BY、HAVING、UNION或者由多表连接生成且更新列来自多张表基本都不可更新。v_student_dept是两表连接更新Sname这种只来自单表的列通常可行但更新涉及连接键的列就会失败。WITH CHECK OPTION的作用是另一回事它管的是写入的数据必须仍然满足视图的过滤条件否则拒绝防止通过视图插进去一行在视图里根本看不见的记录。4.2 完整性控制先让数据库自己拒绝再考虑用触发器兜底完整性实验的核心不是把约束建上去而是验证约束真的会拦人。我一般会故意造几条违规数据把报错信息记下来写进报告里比一句“约束生效”有说服力。-- 造一条引用不存在学生的选课记录观察报错里带的约束名 INSERT INTO SC(Sno, Cno, Grade) VALUES (S9999, C01, 80); -- 成绩允许为空缓考但不允许负数或超过 100 ALTER TABLE SC ADD CONSTRAINT ck_sc_grade CHECK (Grade IS NULL OR (Grade 0 AND Grade 100)); -- 级联行为要显式声明默认是 NO ACTION删父表行会被拦下 ALTER TABLE SC DROP CONSTRAINT fk_sc_student; ALTER TABLE SC ADD CONSTRAINT fk_sc_student FOREIGN KEY (Sno) REFERENCES Students(Sno) ON DELETE CASCADE;五类约束的定位要分清主键管唯一且非空UNIQUE管唯一但允许空且允许多个空值NOT NULL只管非空CHECK管取值区间和枚举外键管跨表引用。前四类都是单表内的事只有外键牵扯两张表所以它的删除行为必须显式指定——ON DELETE CASCADE会连带删掉从表里的引用行ON DELETE RESTRICT默认行为会拒绝删除两者在实验五的验证里应该都跑一遍看报错和连锁效果。触发器是约束表达不了的复杂规则才用的。比如“学生退课必须先把成绩归档到历史表”CHECK写不出来得用CREATE TRIGGER挂一个行级触发器。我的建议是实验阶段先不上触发器把五类约束吃透等到确实需要跨表业务规则时再引入因为触发器调试成本高报错信息往往指向触发函数内部新手容易迷失。4.3 安全性控制能连库、能用 schema、能查表三道权限门缺一不可这一节的权限模型是本份报告里最实用、也最容易只做一半的部分。新建一个用户授予SELECT然后用新用户去查查不到——很多人到这里就以为权限没生效其实是漏了另外两层的授权。-- 建可登录的角色密码按实际口令策略给别照抄示例 CREATE ROLE r_query WITH LOGIN PASSWORD Gauss12345; -- 三道门连接数据库、使用 schema、访问表少一道都查不出数据 GRANT CONNECT ON DATABASE db_school TO r_query; GRANT USAGE ON SCHEMA book_eg TO r_query; GRANT SELECT ON Students, Courses, SC TO r_query; -- 验证 REVOKE 是即时生效的收回单表查询权后再查应该报权限不足 REVOKE SELECT ON Courses FROM r_query; -- 把角色授予具体用户权限按角色收敛别给每个用户单独配一遍 GRANT r_query TO u_zhang;这三道门的顺序对应数据库的对象层级库是一层schema 是库内的一层表和视图是最内层。CONNECT决定能不能连上这个库USAGE决定能不能“看见”这个 schema 里的对象表级SELECT决定能不能读数据。只授予表权限没给 schema 的USAGE查询时报的是对象不存在而不是权限不足这个错误提示极其误导是踩坑率最高的一个点。角色和用户的区分在实验六里第一次变得具体。用户是能登录的账户角色是权限集合一个角色可以授予多个用户也可以授予另一个角色形成层级。公司里有多个库管员把“库管”这个角色的权限配一次新入职的人直接授予角色调岗的人收回角色不用逐个改权限。这也是报告书里那段用仓库管理员做的类比真正想讲的东西。4.4 事务与并发控制用两个会话看锁比背隔离级别有用实验七单看 SQL 语句很短难的是理解“另一个会话里能看到什么”。光看语句记不住得开两个gsql窗口对着做。-- 会话 A一个带保存点的事务 BEGIN; UPDATE SC SET Grade Grade 5 WHERE Sno S01 AND Cno C01; SAVEPOINT sp1; UPDATE SC SET Grade Grade 5 WHERE Sno S01 AND Cno C02; ROLLBACK TO sp1; -- 只回滚到保存点第一条更新仍在事务中 COMMIT;-- 会话 B查当前被锁的关系、锁模式、持锁的会话与被阻塞的语句 SELECT l.locktype, l.relation::regclass AS object_name, l.mode, l.granted, a.pid, a.state, a.query FROM pg_locks l JOIN pg_stat_activity a ON l.pid a.pid WHERE l.relation IS NOT NULL; -- 隔离级别要在事务的第一条语句之前设置中途改不生效 BEGIN; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;SAVEPOINT和ROLLBACK TO的组合用来演示部分回滚适合写在报告里说明“事务不是全有全无保存点让回滚能精确到某一步”。并发部分则靠第二个窗口观察会话 A 未COMMIT时会话 B 去UPDATE同一行会被阻塞pg_locks里能看到一个granted false的记录pg_stat_activity的state显示active且query停在等锁的那条语句上。这比背“读未提交、读已提交、可重复读、串行化”四个名字直观得多。一个真实的连带影响是长事务不提交会挡住ALTER TABLE。实验五给SC加CHECK约束时如果另一个窗口还挂着未提交的更新ALTER TABLE会一直等锁没有任何报错就是卡住不动。遇到“DDL 执行不下去”先查pg_locks八成是有人忘了COMMIT。5. 避坑与排查九个实验里复现率最高的五个卡点下面五条是我在带着别人重做这套实验时反复见到的按现象、原因、解决写清楚照着对号入座就行。5.1 环境与连接命令找不到、端口对不上坑一gsql: command not found但数据库明明装着。现象是切到安装用户后敲gsql提示找不到命令ls到安装目录里却能看见那个二进制文件。原因多半是su omm少了中间那个横杠登录 shell 没启动.bashrc里的环境变量没被加载少数情况是装的时候没把环境变量写进配置文件只在当前会话临时export过。解决办法有两个层次日常操作固定用su - omm确认环境是否正常敲echo $GAUSSHOME有输出说明路径已加载再which gsql确认二进制在PATH里。长期解法是把export那几行写进~/.bashrc退出重登一次。坑二服务状态正常客户端就是连不上。现象是gs_om -t status --detail显示节点 Normalgsql -d postgres -p 26000却报连接失败。原因有三个分支端口不是 26000装的时候改过或者多实例部署了别的端口从远程机器连pg_hba.conf里没有放行这个来源 IP服务是起来了但监听地址只绑了本地回环。解决顺序是先读status --detail里的实际端口用那个端口重连远程连接失败的去数据目录下看pg_hba.conf追加对应来源的host记录后重新加载配置别用重启代替最后用netstat一类的工具确认监听地址。日志在$GAUSSLOG/pg_log下连不上时先翻最新的那个文件报错原因通常就在第一屏。5.2 对象与权限表建完不见了、权限给了还查不到坑三CREATE TABLE成功\dt列表却是空的。现象很统一——建表语句返回成功\dt一片空白于是怀疑表没建成。原因是表落到了当前搜索路径没覆盖的 schema 里。两种情况最常见显式写了book_eg.Teachers这种带前缀的名字表进了book_eg或者用某个用户建表表进了与该用户同名的 schema而当前连接的用户不是它。解决办法是三步定位SELECT current_schema();看搜索路径落在哪\dn列出所有 schema\dt *.*把全库的表都列出来找到目标表后用\d schema名.表名查看结构。要在不带前缀的情况下直接访问把目标 schema 加进搜索路径即可。坑四GRANT SELECT执行成功新用户查询报对象不存在。现象是新用户连上了库执行SELECT * FROM Students;报对象或 schema 不存在报错信息跟权限毫无关系。原因就是 4.3 提到的三道门只开了两道给了CONNECT和表级SELECT漏了USAGE ON SCHEMA。数据库在解析表名时先要能“看见”这个 schema看不见就当作对象不存在不会提示权限不足。解决办法是把三层授权补齐库级CONNECT、schema 级USAGE、表级SELECT或更细的列级授权。验证方式是切到新用户重新连接后再查权限变更对已建立的会话不一定立刻生效重连最稳妥。5.3 备份恢复导出来了恢复了数据却少了坑五备份文件恢复后角色、表空间、部分对象全没了。现象是用gs_dump导出单库恢复到新环境后表和数据都在但原本依赖的角色不存在、自定义表空间没建、访问时报各种找不到。原因是gs_dump的粒度就是单个数据库。它导出库内的对象和数据不负责实例级的全局对象——角色、表空间这些属于实例层面不在单库备份的范围内。恢复目标环境如果是个干净实例这些前置对象本来就缺。解决办法分两种整实例迁移用gs_dumpall它会把全局对象一并导出只迁单库就分两步走先在新实例手工建好角色和表空间再用gs_dump导出的文件恢复。另外恢复到一个不存在的库会直接失败目标库必须先CREATE DATABASE建好空壳这条在实验八里几乎人人踩一次。6. 备份格式与 JDBC怎么证明自己不是“跑了一遍”而是真的跑通了实验八和实验九最容易出现“过程全对、结果说不清”的情况。备份恢复要能证明数据一条不少JDBC 要能证明连接真的通到了那个库而不是只编译通过。6.1 两种备份格式的差别与恢复路径文本格式可读、能直接改适合小库和看结构自定义格式体积小、支持选择性恢复单表适合做真正的备份。格式参数产物恢复方式适用场景-F p纯 SQL 文本gsql -f执行看结构、改数据、小库迁移-F c自定义二进制gs_restore常规备份、按表恢复# 自定义格式导出单库-f 指定输出文件路径要落在安装用户有写权限的目录 gs_dump -U omm -W Gauss12345 -p 26000 -F c -f /home/omm/backup/db_school.dmp db_school # 恢复前目标库必须先存在gs_restore 不会替你建库 gs_restore -U omm -W Gauss12345 -p 26000 -d db_school_bak /home/omm/backup/db_school.dmp验证方法我固定用三步恢复前在源库SELECT count(*) FROM SC;记下数字恢复后在目标库跑同一条语句比对再抽查一条具体记录确认字段值一致最后\dt对比表数量。三步都过才算恢复成功只看命令返回值不算。6.2 JDBC 那一步的验证点连上、查到、关掉// 驱动类名按 jar 包版本不同可能是 org.opengauss.Driver 或 org.postgresql.Driver // 拿不准就解压 jar看 META-INF/services/java.sql.Driver 里写的是哪个 Class.forName(org.opengauss.Driver); try (Connection conn DriverManager.getConnection( jdbc:opengauss://127.0.0.1:26000/db_school, omm, Gauss12345); Statement st conn.createStatement(); ResultSet rs st.executeQuery(SELECT count(*) FROM Students)) { rs.next(); System.out.println(学生表行数 rs.getInt(1)); }连接串四段分别是协议、主机、端口、库名端口必须和status --detail里的一致。报No suitable driver基本是驱动类名和 jar 版本对不上翻 jar 里的服务声明文件最快。能查出数字说明链路全通查不出来但连接没报错多半又是 schema 搜索路径的问题回到 5.2 的坑四。从那以后我每次做完恢复实验都会强制跑一遍“数行数、抽一行、数表数”这套动作再让 JDBC 那边打印一次表行数——两个数字对得上报告才敢交。希望帮到你。本文还有配套的精品资源点击获取