☰
GreatSQL数据库原理实验:从环境搭建到SQL查询的完整实操指南
2026/10/13 16:29:31 网站建设 项目流程

简介:这份资源是郑州大学计算机与人工智能学院《数据库系统原理》课程的实验报告文档,面向修读该课程的学生及需要了解数据库实验流程的学习者。报告围绕万里数据库GreatSQL展开,涵盖DBMS系统认识、数据库逻辑与物理组件、环境配置与依赖安装、服务启停管理以及实验结果分析等内容,并附有实验截图、图表编号与规范排版,可作为实验操作与报告撰写的参考模板。资源包内共1个docx文件,约3.69MB,内容完整、结构清晰,便于直接查阅与借鉴。目前已有507人学习下载,适合希望系统掌握数据库实验步骤、理解配置原理与排错思路的读者参考使用。

1. 从零搭一套 GreatSQL 实验环境:这份数据库原理实验报告能帮你省下多少试错时间

如果你正在上《数据库系统原理》这门课,或者需要带学生做 DBMS 认知实验,大概率会遇到一个很现实的问题:教材上讲的基本表、视图、触发器、存储过程这些逻辑组件,落到真实环境里到底长什么样?光看 PPT 很难有体感。这份实验报告围绕万里数据库 GreatSQL 展开,从虚拟机环境配置、二进制包安装、systemd 服务管理,一路做到建库建表、索引创建、交互式 SQL 查询,九个实验串成一条完整的动手链路。它适合两类人:一是正在跟这门课、需要照着步骤复现实验并写报告的学生;二是想快速了解国产数据库 GreatSQL 基本操作、但不想从官方手册第一页翻起的开发者。报告里记录的命令和参数选择,都是实际跑通过的,不是纸上谈兵。

2. 环境准备与 GreatSQL 安装:从 SELinux 关闭到 systemd 托管的完整链路

2.1 为什么先关 SELinux 和防火墙

很多新手拿到虚拟机第一件事就是装数据库,结果卡在服务起不来、端口连不上,翻来覆去查日志也看不出所以然。这份报告的做法是先把 SELinux 和防火墙处理掉,再装数据库。这不是偷懒,而是实验环境下的务实选择。

SELinux 是强制访问控制机制,它会限制进程能碰哪些文件、能开哪些端口。数据库进程需要读写数据目录、监听网络端口,这些操作在 SELinux 的默认策略下经常被拦截。实验环境里我们不需要那么严格的安全隔离,关掉它可以避免大量权限相关的玄学问题。防火墙同理,GreatSQL 默认监听 3306 端口,如果防火墙没放行,客户端根本连不上。

操作命令如下:

# 临时关闭 SELinux(当前会话生效) setenforce=0 # 永久关闭 SELinux(修改配置文件,重启后生效) sed -i '/^SELINUX=/c'SELINUX=disabled /etc/selinux/config # 停止并禁用防火墙 systemctl disable firewalld systemctl stop firewalld

这里有个细节值得注意:setenforce=0只对当前运行状态生效,重启后就恢复了。真正要持久关闭,必须改/etc/selinux/config文件,把SELINUX那一行改成disabled。两条命令配合使用才算完整。防火墙的disable和stop也是同理,一个管开机自启,一个管当前状态。

提示:生产环境不要照搬这个做法。实验环境关 SELinux 和防火墙是为了减少干扰,真实服务器上应该配置精细的 SELinux 策略和防火墙规则。

2.2 依赖包安装与二进制包部署

GreatSQL 提供的是二进制包,不需要编译,但依赖一些系统库。报告里列出的依赖包比较多,我按功能分类说明一下:

yum install -y pkg-config perl libaio-devel numactl-devel numactl-libs \ net-tools openssl openssl-devel jemalloc jemalloc-devel \ perl-Data-Dumper perl-Digest-MD5 python2 perl-JSON perl-Test-Simple
  • libaio-devel:异步 I/O 支持,InnoDB 存储引擎依赖它做磁盘读写
  • numactl-devel和numactl-libs:NUMA 架构下的内存分配优化,多核服务器上影响性能
  • openssl和openssl-devel:SSL 连接和加密函数依赖
  • jemalloc和jemalloc-devel:内存分配器,GreatSQL 用它替代默认的 malloc 提升性能
  • perl相关包:一些管理脚本和测试工具用 Perl 写的

这些包缺一个都可能导致后续启动失败,建议一次性装完。装完后下载二进制包并解压:

cd /usr/local wget https://product.greatdb.com/GreatSQL-8.0.32-25/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal.tar.xz tar xf GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal.tar.xz

解压后目录名很长,后面配置文件和 service 文件里都要写完整路径,建议先确认一下实际目录名。接下来创建 mysql 用户和用户组,因为数据库进程不应该用 root 跑:

/sbin/groupadd mysql /sbin/useradd -g mysql mysql -d /dev/null -s /sbin/nologin

-d /dev/null表示不分配家目录,-s /sbin/nologin表示不允许登录 shell。这是服务账号的标准做法,减少安全风险。

然后创建数据目录并授权:

mkdir /var/lib/mysql/ chown -R mysql:mysql /var/lib/mysql/ /var/log /usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal

2.3 systemd 服务配置与启动验证

把 GreatSQL 注册成 systemd 服务,后面就能用systemctl统一管理。创建服务文件:

vim /lib/systemd/system/greatsql.service

文件内容需要指定 ExecStart、ExecStop、User、Group 等字段,指向实际的二进制路径和数据目录。写完后重载 systemd:

systemctl daemon-reload systemctl start greatsql

启动后别急着操作,先确认服务状态和进程:

systemctl status greatsql ps -ef | grep mysqld ss -lntp | grep mysqld

systemctl status看服务是否 active,ps确认 mysqld 进程存在,ss检查 3306 端口是否在监听。三个都正常,说明数据库真的起来了。最后看一眼数据目录:

ls /var/lib/mysql

应该能看到 ibdata1、ib_logfile 等 InnoDB 的系统文件,以及 mysql、sys 等系统库目录。这一步是验证安装是否完整的关键,如果数据目录是空的,说明初始化没成功,需要检查配置文件里的 datadir 路径是否正确。

3. 建库建表与索引操作:SQL 语句背后的数据类型和约束选择

3.1 数据库创建与存储位置查看

实验二的核心是创建数据库 DB,然后建三张表:STUDENTS、COURSES、SC。先看建库:

CREATE DATABASE DB; SHOW DATABASES; USE DB;

SHOW DATABASES确认 DB 已创建,USE DB切换到该库。建完后可以查看数据库的存储位置和文件信息:

SHOW VARIABLES LIKE 'datadir';

这会返回数据目录的路径。每个数据库对应 datadir 下的一个子目录,里面存放该库的表结构文件(.frm 或 .ibd)和表空间文件。理解这一点对后续排查磁盘空间问题很有帮助。

3.2 基本表创建:从草稿表到正式表

报告里先建了三张简单表做测试,然后删掉重建正式表。这个流程值得说一下:先用简单结构验证语法和连接没问题,再上正式结构,避免一上来就写复杂 SQL 出错后不好定位。

草稿表:

CREATE TABLE STUDENTS(id int primary key, name varchar(60)); CREATE TABLE COURSES(cid int primary key, cname varchar(60)); CREATE TABLE SC(id int, cid int, primary key(id,cid), grade int);

正式表:

CREATE TABLE STUDENTS( Sno char(9) PRIMARY KEY, Sname char(10) NOT NULL, Sex char(2), Birthday DATE, Speciality char(20), Dno char(4) ); CREATE TABLE Courses( Cno char(5) PRIMARY KEY, Cname char(20) NOT NULL, Period int, Credit int ); CREATE TABLE SC( Sno char(9), Cno char(5), Grade int, PRIMARY KEY (Sno,Cno) );

这里有几个参数选择值得展开。Sno用char(9)而不是varchar,因为学号是定长的,char 在存储和比较时效率略高。Sname加了NOT NULL约束,确保学生姓名不能为空。SC表用(Sno, Cno)做复合主键,保证同一个学生同一门课只有一条成绩记录。Grade用int类型,虽然成绩可以是小数,但实验场景下整数够用。

注意:char和varchar的选择不是绝对的。char 适合定长字段,varchar 适合变长字段。如果字段长度变化大,用 varchar 更省空间。

3.3 数据填充与索引创建

建完表后插入数据:

INSERT INTO STUDENTS VALUES ('201705001', '张华', '男', '1999-12-16', '计算机', 'CS'), ('201705002', '张晓霞', '女', '1999-01-01', '软件工程', 'SE'), ('201706001', '李玉', '女', '1999-10-17', '数学', 'MA'); INSERT INTO COURSES VALUES ('CS101', '计算机科学导论', 2, 1), ('CS102', '数据库系统', 4, 4), ('CS103', '操作系统', 4, 3); INSERT INTO SC VALUES ('201705001', 'CS101', 89), ('201705002', 'CS102', 92), ('201705003', 'CS101', 88);

插入时注意日期格式,GreatSQL 默认接受YYYY-MM-DD格式。如果写成1999_12_16会报错,报告里后面实验三的插入语句就踩了这个坑,需要留意。

索引创建:

CREATE INDEX Student_Dept ON Students (Dno); CREATE UNIQUE INDEX Course_Cno ON Courses (Cno);

Student_Dept是普通索引,加速按系号查询。Course_Cno是唯一索引,除了加速查询还保证课程号不重复。删除索引:

DROP INDEX Course_Cno ON Courses;

索引不是越多越好。每个索引都会增加插入和更新时的开销,因为数据库要同时维护索引结构。实验里建两个索引是为了演示语法,实际项目中要根据查询模式来决定建哪些索引。

4. 交互式 SQL 查询与更新:从单表查询到多表关联的实操要点

4.1 建表时的外键与约束设计

实验三重新建了一套更完整的表结构,包含 Departments、Teachers、Students、Courses、SC、Teaches 六张表。这套表结构比实验二复杂,涉及外键关联。先看建表:

CREATE TABLE Departments( Dno char(4) PRIMARY KEY, Dname char(20), Dheadno char(7) ); CREATE TABLE Teachers( Tno char(7) PRIMARY KEY, Tname char(10) NOT NULL, Sex char(2) CHECK(Sex = '男' OR Sex = '女'), Birthday DATE, Title char(10), Dno char(4) ); CREATE TABLE Students( Sno char(12) PRIMARY KEY, Sname char(20) NOT NULL, Birthday DATE, Speciality char(20), Dno char(4), Sex char(4) ); CREATE TABLE Courses( Cno char(5) PRIMARY KEY, Cname char(30) NOT NULL, Period SMALLINT, Credit SMALLINT ); CREATE TABLE SC( Sno char(12), Cno char(5), Grade int CHECK(Grade > 0 AND Grade <= 100), PRIMARY KEY (Sno, Cno), FOREIGN KEY (Sno) REFERENCES Students (Sno), FOREIGN KEY (Cno) REFERENCES Courses (Cno) ); CREATE TABLE Teaches( Tno char(7), Cno char(5), TCsores int, PRIMARY KEY (Tno, Cno) );

这里有几个设计点。Teachers表的Sex字段加了CHECK约束,只允许“男”或“女”。SC表的Grade加了CHECK(Grade > 0 AND Grade <= 100),防止成绩超出合理范围。SC表还定义了两个外键,分别指向Students和Courses,保证成绩记录不会引用不存在的学生或课程。

Teaches表建的时候没加外键,后面用ALTER TABLE补上:

ALTER TABLE Teaches ADD FOREIGN KEY (Cno) REFERENCES Courses(Cno); ALTER TABLE Teaches ADD FOREIGN KEY (Tno) REFERENCES Teachers(Tno); ALTER TABLE Students ADD FOREIGN KEY (Dno) REFERENCES Departments(Dno); ALTER TABLE Teachers ADD FOREIGN KEY (Dno) REFERENCES Departments(Dno);

这种先建表后加外键的做法在实际项目中很常见,因为建表时如果依赖的表还没创建,外键会失败。先建所有表,再统一加外键,顺序更灵活。

4.2 查询操作:WHERE、IN、BETWEEN 的用法与边界

数据插入完成后,开始查询操作。报告里覆盖了几种典型查询模式,我挑几个有代表性的说。

不带 WHERE 的查询:

SELECT * FROM Courses; SELECT Sname, 2024 - YEAR(Birthday) AS Age FROM Students;

第二条用YEAR()函数提取出生年份,用当前年份减去得到年龄。这里2024是硬编码的,实际使用中可以用YEAR(CURDATE())动态获取当前年份。

带 WHERE 的查询:

SELECT Tname, Sex FROM Teachers WHERE Title = '讲师'; SELECT DISTINCT Sno FROM SC WHERE Grade < 60; SELECT Sname, Speciality FROM Students WHERE YEAR(Birthday) BETWEEN 1997 AND 1999; SELECT Sname, Speciality FROM Students WHERE YEAR(Birthday) NOT BETWEEN 1997 AND 1999;

DISTINCT用于去重,因为一个学生可能有多门不及格,不加 DISTINCT 会返回重复学号。BETWEEN是闭区间,包含两端值。NOT BETWEEN则排除这个区间。

IN 表达式:

SELECT Sno, Sname FROM Students WHERE Speciality IN ('计算机', '软件工程'); SELECT Sno, Sname FROM Students WHERE Speciality NOT IN ('计算机', '软件工程');

IN适合枚举值较少的场景,比多个OR条件写起来简洁。NOT IN则取反。注意NOT IN遇到 NULL 值时有坑:如果子查询返回的结果集中包含 NULL,NOT IN会返回空结果集。实验里直接写常量列表,不涉及这个问题,但实际开发中要留意。

4.3 更新操作与事务边界

报告里更新操作涉及插入、修改和删除。以插入为例:

INSERT INTO Courses VALUES ('cs101', '计算科学导论', 2, 1), ('cs102', 'C 语言', 4, 3), ('cs201', '数据结构', 4, 3), ('cs202', '离散数学', 4, 3), ('cs301', '数据库系统原理', 4, 3);

这里课程号用了小写cs101,而实验二里用的是大写CS101。GreatSQL 默认对字符类型比较不区分大小写(取决于排序规则),但建议统一风格,避免混淆。

修改和删除操作:

UPDATE SC SET Grade = 95 WHERE Sno = '201705001' AND Cno = 'cs101'; DELETE FROM SC WHERE Grade < 60;

UPDATE和DELETE一定要带WHERE条件,否则会更新或删除全表数据。这是血泪教训,新手很容易犯。执行前先用SELECT确认条件范围,是个好习惯。

提示:GreatSQL 支持事务,InnoDB 存储引擎下UPDATE和DELETE可以通过ROLLBACK回滚。但前提是没执行COMMIT,且用的是事务型存储引擎。

5. 实验报告撰写与常见问题排查:截图规范、环境差异与 SQL 兼容性

5.1 实验报告格式要求与截图规范

报告对格式有明确要求:截图下方要有图编号和图题,表格上方要有编号和表名,段首空两格,行文用书面语。这些要求看似琐碎,但实际提交时格式不规范会被扣分。

截图建议用系统自带的截图工具或gnome-screenshot,截完后统一命名,比如fig1_service_status.png、fig2_mysqld_process.png。在文档里插入后,下方居中写“图1 进程状态”“图2 mysqld进程”。表格用 Markdown 或 Word 表格都行,上方写“表1 学生表结构”之类的标题。

5.2 常见问题排查

现象一:systemctl start greatsql启动失败,状态显示 failed。

原因:数据目录权限不对,或者配置文件路径写错。GreatSQL 进程以 mysql 用户运行,如果 datadir 的属主不是 mysql,进程没有写权限。

解决:检查/var/lib/mysql的属主和属组,用chown -R mysql:mysql /var/lib/mysql修正。同时检查/etc/my.cnf里的datadir和socket路径是否与实际一致。

现象二:客户端连接报“Can't connect to local MySQL server through socket”。

原因:socket 文件路径不匹配。GreatSQL 默认 socket 在/var/lib/mysql/mysql.sock,但客户端可能去/tmp/mysql.sock找。

解决:在/etc/my.cnf的[client]段和[mysqld]段都指定socket路径,保持一致。或者连接时用-S参数指定 socket 路径。

现象三:插入日期数据时报“Incorrect date value”。

原因:日期格式不对。报告里实验三的插入语句用了1999_12_16这种下划线格式,GreatSQL 不认。

解决:改成1999-12-16标准格式。如果一定要用其他格式,可以用STR_TO_DATE()函数转换。

现象四:外键约束导致插入失败。

原因:插入的数据在关联表中不存在。比如往SC表插入Sno='201705004',但Students表里没有这个学号。

解决:先插入主表数据,再插入从表数据。或者临时关闭外键检查:SET FOREIGN_KEY_CHECKS=0;,但生产环境不建议这么做。

现象五:NOT IN子查询返回空结果。

原因:子查询结果集中包含 NULL 值。SQL 的三值逻辑里,NULL NOT IN (..., NULL)结果是 UNKNOWN,不会返回任何行。

解决:在子查询里加WHERE column IS NOT NULL过滤掉 NULL 值。

5.3 标准 SQL 与 GreatSQL 的差异

报告里提到要注意标准 SQL 和 GreatSQL 的相同与不同之处。实际使用中,GreatSQL 基于 MySQL 8.0,大部分标准 SQL 都支持,但有些细节有差异。比如YEAR()函数在标准 SQL 里不是内置函数,GreatSQL 提供了。日期格式的解析也比标准 SQL 宽松一些。写 SQL 时如果考虑可移植性,尽量用标准语法;如果只针对 GreatSQL,可以用它的扩展功能。

6. 从实验到实战:用 information_schema 反查数据库对象与性能验证

实验一里有个容易被忽略的操作:通过information_schema查看数据库的逻辑组件。这个系统库是数据库的“黑匣子”,里面记录了所有表、视图、触发器、存储过程、约束的元数据。学会查它,排错和验证效率会高很多。

查看所有基本表:

SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'DB';

查看触发器:

SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'DB';

查看存储过程:

SELECT ROUTINE_NAME, ROUTINE_TYPE FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'DB' AND ROUTINE_TYPE = 'PROCEDURE';

查看约束:

SELECT CONSTRAINT_NAME, TABLE_NAME, CONSTRAINT_TYPE FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = 'DB';

这几个查询在实验报告里可能只是截图交差,但实际工作中非常有用。比如你接手一个陌生的数据库,不知道有哪些触发器在暗中修改数据,查information_schema.TRIGGERS就能一目了然。再比如性能出问题时,查information_schema.KEY_COLUMN_USAGE确认索引是否建对。

验证索引是否生效,可以用EXPLAIN:

EXPLAIN SELECT * FROM Students WHERE Dno = 'CS';

看key列是否显示Student_Dept,rows列估算扫描行数。如果key是 NULL,说明索引没被用上,可能需要检查查询条件是否匹配索引列,或者索引选择性是否太低。

查看数据库物理存储信息:

SHOW VARIABLES LIKE 'innodb_page_size'; SHOW VARIABLES LIKE 'datadir';

innodb_page_size默认 16KB,这是 InnoDB 的最小存储单位。理解这一点对优化大表性能有帮助:一次 I/O 读取一个页,页越小,单次读取快但读取次数多;页越大,单次读取慢但次数少。默认值在大多数场景下是平衡的。

从那以后我每次搭完数据库环境,都会先用information_schema把关键对象扫一遍,确认没有遗漏的触发器或约束,再开始跑业务 SQL。这个习惯帮我省了不少事后排查的时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询