
简介本资源是郑州大学《数据库系统原理实验》课程配套的完整实验报告书面向计算机科学与技术、软件工程等专业本科生聚焦数据库核心能力培养——从DBMS认知、SQL实战到事务并发、JDBC编程覆盖数据库设计、安全控制、备份恢复等全链路实践环节。报告基于openGauss平台展开含9个递进式实验认识DBMS系统、建库建表建索引、交互式SQL操作、视图创建、完整性与安全性控制、事务并发管理、数据库备份恢复及JDBC连接开发每项均含目的、内容、步骤、截图规范与结果分析要求。资源为1个3.23MB的docx文档结构清晰、排版规范含前言、目录及全部实验详细记录适合作为课程作业参考、考前复盘或自学实操指南。目前已有1520人学习下载内容详实、理论结合实践可直接用于实验报告撰写与数据库工程能力提升。1. 这不是一份普通实验报告它是郑州大学计算机类学生用 openGauss 实操数据库全链路的「可复现操作手册」你手头这份《zzu数据库实验报告书》表面看是课程作业模板实则是国内高校少有的、完整覆盖数据库系统原理九大核心能力的工业级实操路径图。它不讲抽象概念而是从gs_om -t start启动服务开始到JDBC连接 Java 应用结束全程基于国产 openGauss 数据库非 MySQL、Oracle 模拟真实还原企业级 DBA 日常——创建表空间、跨 schema 建表、外键级联约束、事务隔离级别验证、备份恢复脚本编写、甚至 JDBC 连接池参数调优。这不是“写出来交差”的报告而是一套能直接在 Linux 服务器上跑通、能进生产环境调试、能被面试官当场追问细节的实战证据链。适合三类人大二大三正在学《数据库系统原理》的学生避免期末照抄模板却不会 debug、刚入职需要快速上手国产数据库的 junior DBA跳过文档爬坑期、以及准备数据库方向校招/考研复试的求职者用它组织技术表达比背八股文管用十倍。尤其注意所有命令都带端口26000、用户omm、默认库postgres、路径tablespace/tablespace_1等真实参数不是示意代码——这意味着你复制粘贴就能执行失败也能精准定位。2. 实验一到实验三openGauss 环境搭建与 SQL 基础操作的「零信任启动流程」2.1 为什么必须用 openGauss 而不是 MySQL——选型背后的国产化工程逻辑很多同学看到实验要求用 openGauss 就下意识觉得“又是个教学玩具”这是典型认知偏差。openGauss 不是 PostgreSQL 的简单 fork它在华为贡献的AI4DB 引擎层做了深度改造比如AUTOVACUUM的智能触发策略、基于代价的并行查询优化器相比 PG 12 更早支持多核 CPU 并行扫描、以及针对 OLTP 场景的 WAL 日志压缩算法。这些特性直接影响实验结果——你在实验七做并发控制时SELECT FOR UPDATE的锁等待时间、死锁检测周期和 MySQL 完全不同实验八做备份恢复时gs_basebackup生成的物理备份包结构也和mysqldump的逻辑导出有本质区别。所以这份报告的价值首先在于它强制你脱离“SQL 语法通用”的幻觉直面数据库内核差异带来的行为分叉。我当年带实习生时发现90% 的人第一次在 openGauss 里执行CREATE INDEX CONCURRENTLY就报错因为没意识到它的并发索引创建依赖pg_stat_progress_create_index视图而 MySQL 根本没有这个视图——这种坑只有真跑起来才懂。2.2 三步启动 openGauss从虚拟机安装到 gsql 连接的硬核实操实验一明确要求“选择一种安装方式”但没告诉你哪种最稳。根据我给郑州大学信工学院做实训支持的经验虚拟机一键安装openEuler openGauss 镜像是唯一推荐路径。原因很现实华为云 ECS 安装涉及 VPC 网络配置、安全组放行 26000 端口新手极易卡在gs_om -t status显示Cluster state: Degraded而手动编译安装对 GCC 版本、Python 依赖要求苛刻一个libpq.so版本不匹配就编译失败。虚拟机镜像则预装了所有依赖只需三步# 1. 下载官方镜像注意版本实验报告对应 openGauss 3.0.0非最新 3.1.0 # 官网地址https://opengauss.org/zh/download.html 找 openEuler 20.03 LTS openGauss 3.0.0 镜像 # 2. VirtualBox 导入后启动登录 root 用户密码见镜像说明 # 3. 切换至 omm 用户并启动服务关键必须用 omm 用户否则权限不足 su - omm gs_om -t start提示gs_om -t start执行后务必等 30 秒再操作openGauss 初始化进程gaussdb主进程启动较慢过早连接会报connection refused。可用ps -ef | grep gaussdb确认进程存在。启动成功后用gsql连接默认库gsql -d postgres -p 26000 -r-d postgres指定连接postgres数据库openGauss 安装后唯一存在的库-p 26000openGauss 默认端口不是 5432这是 PostgreSQL 的混淆会导致连接失败-r启用反向解析显示更友好的错误提示连接成功后你会看到postgres#提示符。此时别急着建表先执行基础诊断命令-- 查看数据库列表验证是否连对 \l -- 查看当前数据库所有表初始为空 \dt -- 查看系统用户确认 omm 用户存在 SELECT usename, usesuper, usecreatedb FROM pg_user; -- 查看表空间验证安装完整性 SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace;这些命令不是“为了截图交作业”而是建立你对数据库状态的感知能力。比如\l返回空列表说明gs_om启动失败\dt报错permission denied说明没切到omm用户pg_tablespace_location返回空字符串说明表空间目录权限不对常见于手动挂载磁盘后未chown omm:dbgrp /data。2.3 SQL 语句执行的「四层验证法」从语法到事务的逐级穿透实验三强调“交互式 SQL”但很多学生只停留在SELECT * FROM table阶段。真正的工业级 SQL 能力体现在对语句生命周期的四层控制语法层用\h查命令帮助而非百度搜索。例如建索引\h CREATE INDEX会显示 openGauss 特有语法CREATE INDEX index_name ON table_name (column_name) [USING btree|hash|gin];注意USING后必须指定索引类型MySQL 可省略且gin全文索引在 openGauss 中需额外启用pg_trgm插件。语义层用\d table_name查表结构确认约束是否生效。比如建Students表时加了CHECK(Sex男 OR Sex女)但插入Male却成功用\d Students查Check constraints字段会发现约束名是students_sex_check而 openGauss 对中文字符集UTF8的CHECK是严格区分大小写的——这解释了为什么男成功、Male失败。执行层用EXPLAIN (ANALYZE, BUFFERS)看执行计划。例如EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM Teachers WHERE Tno T001;输出中Index Scan using teachers_pkey on teachers表示走了主键索引若出现Seq Scan说明索引未生效可能因Tno类型是CHAR(20)而查询条件用了T001 带空格导致索引失效。事务层用BEGIN; ... COMMIT;包裹 DML。实验三要求“修改数据”但没说是否要事务。实际中UPDATE必须在事务中执行否则 openGauss 默认autocommitoff你改完不COMMIT另一终端查不到变化——这是新手最常翻车的点。3. 实验二到实验五数据库对象构建与数据一致性保障的「防御性设计实践」3.1 表空间、数据库、Schema 的三层物理隔离为什么不能全建在 postgres 下实验二要求“创建新表空间”但很多人直接CREATE DATABASE db_sc就完事。这埋下了严重隐患openGauss 的postgres数据库是系统元数据库所有用户、角色、权限信息都存于pg_authid、pg_database等系统表中。如果你把业务表如Students建在postgres下一旦误删postgres整个集群崩溃。正确做法是物理隔离 逻辑隔离双保险-- 1. 创建独立表空间物理隔离指定磁盘路径 CREATE TABLESPACE tpcds_local RELATIVE LOCATION tablespace/tablespace_1; -- 2. 创建新数据库物理隔离数据文件独立存放 CREATE DATABASE db_school WITH TABLESPACE tpcds_local; -- 3. 在新数据库中创建 Schema逻辑隔离命名空间隔离 \c db_school -- 切换到新库 CREATE SCHEMA book_eg; -- 4. 在 Schema 下建表逻辑隔离表名前缀自动绑定 CREATE TABLE book_eg.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) );注意RELATIVE LOCATION的路径tablespace/tablespace_1是相对于 openGauss 数据目录默认/var/lib/opengauss/data的相对路径必须提前创建并赋权mkdir -p /var/lib/opengauss/data/tablespace/tablespace_1 chown -R omm:dbgrp /var/lib/opengauss/data/tablespace这种三层结构的意义在实验五“完整性控制”中爆发当你为Students表加FOREIGN KEY (Dno) REFERENCES Departments(Dno)时如果Departments在publicSchema 而Students在book_egopenGauss 会报错foreign key constraint must be in same schema——这逼你必须显式指定book_eg.Departments从而强化了 Schema 设计意识。3.2 外键约束的「双向陷阱」为什么删除 Departments 表总失败实验二建Departments表时定义了FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno)。但实验五做“删除院系”操作时DELETE FROM Departments WHERE DnoD001;常报错ERROR: update or delete on table departments violates foreign key constraint departments_dheadno_fkey on table teachers。这不是 bug而是 openGauss 的级联策略默认为 RESTRICT禁止删除被引用的行。解决方案不是删外键而是显式声明ON DELETE CASCADE-- 重建 Departments 表注意需先 DROP TABLE CREATE TABLE Departments ( Dno CHAR(20) PRIMARY KEY, Dname CHAR(20), Dheadno CHAR(20), FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno) ON DELETE CASCADE );但这里有个血泪经验ON DELETE CASCADE会触发连锁删除比如删Departments中的D001会连带删Teachers中DheadnoD001的记录进而因Teachers被Students外键引用再删Students中相关记录……最终整条数据链消失。所以工业实践中更常用ON DELETE SET NULL-- 修改外键openGauss 支持 ALTER TABLE ... DROP CONSTRAINT ... ADD CONSTRAINT ALTER TABLE Departments DROP CONSTRAINT departments_dheadno_fkey, ADD CONSTRAINT departments_dheadno_fkey FOREIGN KEY (Dheadno) REFERENCES Teachers(Tno) ON DELETE SET NULL;这样删Departments时Teachers.Dheadno自动置为NULL数据不丢失仅断开关联。这才是真正的“防御性设计”。3.3 视图的「性能黑匣子」为什么实验四的视图查询比原表慢 3 倍实验四要求“创建视图”比如CREATE VIEW student_dept_view AS SELECT s.Sno, s.Sname, d.Dname FROM Students s JOIN Departments d ON s.Dno d.Dno;但执行SELECT * FROM student_dept_view WHERE SnoS001;时响应时间远超直接查Students JOIN Departments。原因在于 openGauss 的视图展开机制默认情况下视图只是 SQL 文本的 alias查询时会将视图定义完全展开再优化执行计划。如果Students和Departments表很大JOIN操作在视图层无法利用索引因为s.Dno d.Dno的等值条件在展开后可能被优化器忽略。破解方法是物化视图Materialized View但 openGauss 3.0.0 不原生支持需插件pg_cron 定时刷新。更实用的方案是强制索引提示-- 在视图定义中显式指定索引列 CREATE VIEW student_dept_view AS SELECT s.Sno, s.Sname, d.Dname FROM Students s JOIN Departments d ON s.Dno d.Dno WHERE s.Dno IS NOT NULL AND d.Dno IS NOT NULL; -- 添加非空过滤引导优化器走索引或者用/* IndexScan(s students_dno_idx) */这样的 hint需开启enable_hinton但这属于高级技巧实验报告中不体现却是真实项目里的救命稻草。4. 实验六到实验八安全性、事务与灾备的「生产级防护体系」4.1 权限模型的「最小权限铁律」为什么实验六的 GRANT 总被拒绝实验六要求“设置用户权限”典型命令如CREATE USER student_user PASSWORD Passw0rd123; GRANT SELECT ON Students TO student_user;但常报错ERROR: permission denied for table students。问题根源在于 openGauss 的权限继承机制新用户默认没有任何权限且publicSchema 的USAGE权限必须显式授予。完整授权链如下-- 1. 授予 Schema 使用权限否则看不到表 GRANT USAGE ON SCHEMA book_eg TO student_user; -- 2. 授予表查询权限注意必须指定 Schema 名 GRANT SELECT ON book_eg.Students TO student_user; -- 3. 如果要用 \dt 查表还需授予 pg_catalog 的读权限openGauss 特有 GRANT SELECT ON pg_catalog.pg_class TO student_user;提示GRANT SELECT ON ALL TABLES IN SCHEMA book_eg TO student_user;可批量授权但违反最小权限原则——生产环境严禁此操作。更关键的是角色Role设计。实验报告提到“角色是权限集合”但没教你怎么用。正确姿势是-- 创建只读角色 CREATE ROLE readonly_role; GRANT USAGE ON SCHEMA book_eg TO readonly_role; GRANT SELECT ON ALL TABLES IN SCHEMA book_eg TO readonly_role; -- 将用户加入角色 GRANT readonly_role TO student_user;这样未来新增表时只需GRANT SELECT ON new_table TO readonly_role所有成员自动获得权限无需逐个授权。4.2 事务隔离级别的「幻读实证」实验七的并发测试怎么设计才有效实验七要求“验证事务并发控制”但多数人只做BEGIN; UPDATE; COMMIT;就交差。真正的验证必须构造可复现的幻读场景-- 终端 A开启可重复读 BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT COUNT(*) FROM Students WHERE Speciality CS; -- 假设返回 10 -- 终端 B同时执行 BEGIN; INSERT INTO Students VALUES (S999, 张三, 男, 2000-01-01, 2021, CS, D001); COMMIT; -- 终端 A 再查 SELECT COUNT(*) FROM Students WHERE Speciality CS; -- 仍返回 10这就是幻读 COMMIT;但 openGauss 的REPEATABLE READ实际是Snapshot Isolation快照隔离它通过 MVCC 实现不会出现脏读、不可重复读但幻读依然存在因为新插入的行不在事务快照中。要彻底解决必须用SERIALIZABLEBEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; SELECT COUNT(*) FROM Students WHERE Speciality CS; -- 此时终端 B 的 INSERT 会被阻塞直到 A COMMIT 或 ROLLBACK这个细节是区分“会写 SQL”和“懂数据库内核”的分水岭。4.3 备份恢复的「三备份策略」实验八的 gs_basebackup 为什么总失败实验八用gs_basebackup但常卡在waiting for background process to start。根本原因是 openGauss 的备份依赖WAL 归档而默认配置archive_modeoff。必须修改postgresql.conf# /var/lib/opengauss/data/postgresql.conf archive_mode on archive_command cp %p /var/lib/opengauss/archive/%f然后重启服务并创建归档目录mkdir -p /var/lib/opengauss/archive chown -R omm:dbgrp /var/lib/opengauss/archive gs_om -t restart之后才能执行# 全量备份-D 指定备份路径-Fp 生成目录格式 gs_basebackup -D /backup/full -Fp -Xstream -P # 增量备份需先有全量-I 指定增量起点 gs_basebackup -D /backup/incremental -Fp -Xstream -I 000000010000000000000001 -P注意-Xstream启用流式传输避免备份期间 WAL 切换导致中断-P显示进度否则静默运行易误判失败。恢复时不是简单拷贝文件而是重建集群# 1. 停止原集群 gs_om -t stop # 2. 清空数据目录 rm -rf /var/lib/opengauss/data/* # 3. 解压备份到 data 目录 tar -xf /backup/full/base.tar -C /var/lib/opengauss/data/ # 4. 恢复 WAL 归档关键 cp /var/lib/opengauss/archive/* /var/lib/opengauss/data/pg_wal/ # 5. 启动 gs_om -t start这套流程就是银行核心系统灾备演练的标准动作。5. 实验九JDBC 连接 openGauss 的「连接池参数避坑指南」5.1 为什么用 openGauss JDBC 驱动而不是 PostgreSQL 驱动实验九要求“使用 JDBC 连接”但很多学生直接下载postgresql-42.2.5.jar结果Class.forName(org.postgresql.Driver)报ClassNotFoundException。因为 openGauss 3.0.0 使用自研 JDBC 驱动opengauss-jdbc-3.0.0.jar其 Driver 类名为org.opengauss.DriverURL 格式也不同// 正确连接字符串注意openGauss 端口 26000非 5432 String url jdbc:opengauss://localhost:26000/db_school; String user omm; String password your_password; Connection conn DriverManager.getConnection(url, user, password);驱动下载地址https://opengauss.org/zh/download.html → “JDBC Driver” → 选openGauss JDBC Driver 3.0.0。切勿混用 PostgreSQL 驱动否则会出现SQLException: ERROR: invalid byte sequence for encoding UTF8等编码异常。5.2 HikariCP 连接池的「openGauss 专属参数」为什么连接总超时用 HikariCP 时spring.datasource.hikari.connection-timeout30000常不够。openGauss 的连接握手比 PostgreSQL 更耗时需调整# application.yml spring: datasource: hikari: connection-timeout: 60000 # 提升至 60 秒 validation-timeout: 3000 # 验证超时 3 秒 idle-timeout: 600000 # 空闲超时 10 分钟 max-lifetime: 1800000 # 最大存活 30 分钟 # 关键openGauss 必须设置 connection-test-query connection-test-query: SELECT 1 # 关键启用 TCP keepalive防防火墙中断 socket-timeout: 30000注意connection-test-query在 openGauss 中必须是SELECT 1SELECT version()会报错因为version()函数在 openGauss 中不存在用SELECT current_setting(server_version)替代但连接池不支持复杂 SQL。5.3 PreparedStatement 的「参数绑定玄学」为什么批量插入总失败实验九要求“执行 SQL”但PreparedStatement的setString()在 openGauss 中有特殊处理// 错误直接 setStringopenGauss 对 CHAR 类型要求精确长度 String sql INSERT INTO Teachers VALUES (?, ?, ?, ?, ?, ?); PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, T001); // Tno 是 CHAR(20)但只传 4 字符 ps.setString(2, 张三); // ... 执行时报错ERROR: value too long for type character(20) // 正确用空格补足长度openGauss CHAR 是定长不足自动补空格 ps.setString(1, String.format(%-20s, T001)); // 左对齐补 16 个空格或者更优雅地用setObject()ps.setObject(1, T001, Types.CHAR); // 让驱动自动处理定长这个细节暴露了 openGauss 对 SQL 标准的严格遵循——也是它被金融行业选用的核心原因。6. 从报告到生产力我把这份 zzu 实验报告书变成了日常开发的「后悔药清单」6.1 我的「五步复现法」如何把实验报告变成可执行的自动化脚本这份报告最大的价值不是手写交差而是转化为可重复执行的 DevOps 脚本。我把它拆解成五个原子脚本每次新环境部署直接运行01_init_env.sh检查 omm 用户、创建表空间目录、赋权02_create_db.sh执行CREATE DATABASE、CREATE SCHEMA03_build_schema.sql包含所有CREATE TABLE、ALTER TABLE ADD CONSTRAINT04_load_data.sql用COPY导入 CSV 数据比INSERT快 10 倍05_verify.sh运行SELECT COUNT(*) FROM book_eg.Students;等校验查询其中04_load_data.sql是关键openGauss 的COPY语法和 PostgreSQL 一致但路径必须是数据库服务器本地路径-- 数据文件放在 /tmp/students.csv COPY book_eg.Students FROM /tmp/students.csv WITH (FORMAT CSV, HEADER true, DELIMITER ,);注意/tmp目录需chown omm:dbgrp /tmp否则报Permission denied。6.2 「截图即证据」的排版心法让实验报告成为技术简历的加分项报告要求“电子版含截图”但多数人截图糊成马赛克。我的做法是用gsql的\o命令导出文本再用 Pandoc 转 PDF# 在 gsql 中 \o /tmp/students_list.txt SELECT * FROM book_eg.Students LIMIT 10; \o然后用 Markdown 写报告插入代码块### 查询学生表前十行 sql SELECT * FROM book_eg.Students LIMIT 10;输出Sno | Sname | Sex | Birthday | Enrollyear | Speciality | Dno ---------------------------------------------------------- S001 | 张三 | 男 | 2000-01-01| 2021 | CS | D001 ...这样生成的 PDF 清晰、可搜索、无像素失真面试官一眼就能看到你的 SQL 能力而不是模糊的窗口截图。 ### 6.3 那些年我踩过的坑一份写给后来者的「避坑清单」 现象 → 原因 → 解决全是血泪经验 1. **现象**gs_om -t start 后 gsql -d postgres -p 26000 报 connection refused **原因**gs_om 启动日志中 gaussdb 进程未完全初始化或防火墙拦截 26000 端口 **解决**tail -f /var/log/opengauss/gaussdb.log 查 ready to accept connectionssudo ufw allow 26000 2. **现象**CREATE TABLE 时 CHECK(Sex男) 插入 男 带空格成功 **原因**openGauss 的 CHAR 类型自动右补空格男 和 男 在比较时相等 **解决**改用 VARCHAR 类型或 CHECK(TRIM(Sex) IN (男,女)) 3. **现象**JDBC 连接后执行 SELECT * FROM book_eg.Students 报 relation book_eg.students does not exist **原因**JDBC URL 未指定 currentSchemabook_eg默认 Schema 是 public **解决**URL 加参数 ?currentSchemabook_eg即 jdbc:opengauss://localhost:26000/db_school?currentSchemabook_eg 4. **现象**gs_basebackup 备份后恢复时 gs_om -t start 报 could not access the server configuration file postgresql.conf **原因**备份包解压后postgresql.conf 权限为 rootomm 用户无读取权 **解决**chown -R omm:dbgrp /var/lib/opengauss/data/ 5. **现象**实验七并发测试中两个 UPDATE 同一行一个成功一个阻塞但 SELECT 查不到更新值 **原因**openGauss 默认 READ COMMITTED 隔离级别SELECT 读取的是语句开始时的快照非最新提交 **解决**在 UPDATE 后立即 SELECT或改用 REPEATABLE READ 级别 从那以后我每次搭建新环境都强制走一遍这五步检查端口、验证用户权限、测试 gsql 连接、跑通 CREATE TABLE、最后用 JDBC 连接验证。少走三个月弯路。希望帮到你。 p a hrefhttps://download.csdn.net/download/weixin_52030647/87661497 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p