☰
CentOS 7 部署 GreatSQL 数据库:从环境配置到 SQL 实验全流程
2026/10/18 1:16:55 网站建设 项目流程

简介:一份面向郑州大学计算机与人工智能学院《数据库系统原理》课程实验的参考报告,适合校内本科生及初次接触DBMS操作的学习者使用。内容以DBMS工作原理和系统构架为起点,系统覆盖万里数据库GreatSQL的安装配置、启动停止、逻辑组件与物理存储组件,并给出虚拟机VMware+CentOS 7环境下关闭SELinux与防火墙的原因、依赖包安装命令以及二进制包下载解压等实践细节,便于按步骤复现并避开常见配置问题。报告同时体现了实验报告的撰写规范,如实验截图需有编号图题、表格需统一编号等,还包含问题记录、结果分析与反思,可帮助读者理解实验背后的性能与安全考量。压缩包内为1个docx文档,大小3.69MB,内容集中、排版清晰,可直接阅读或参考修改。该资源已有509人浏览学习,对数据库原理实验备查与GreatSQL实操入门都有较高参考价值。

1. 数据库原理实验报告:把 GreatSQL 部署和 SQL 实验一次跑通

这份《数据库系统原理》实验报告,来自某高校计算机与人工智能学院 2023-2024 学年第二学期的课程,核心内容就一件事:在 CentOS 7 虚拟机上把万里数据库 GreatSQL 8.0.32 完整部署起来,再完成建库、建表、索引和交互式 SQL 查询的全流程。它不是纯理论讲义,而是一份能直接对着操作的实战记录。对正在补数据库实验的学生,它能帮你把环境搭建和 SQL 语法一次性理顺;对想快速上手 GreatSQL 的从业者,里面的 systemd 托管、SELinux 处理思路和常见坑位也值得借鉴。接下来的内容按部署、建表、查询、避坑、报告规范五个部分拆开,每步都带原文命令和参数解读。

2. CentOS 7 上部署 GreatSQL:从关闭 SELinux 到 systemd 托管

2.1 环境预配置:为什么先动 SELinux 和防火墙

拿到实验环境第一步不是装数据库,而是先把操作系统层面的拦截关掉。实验报告里明确要求在虚拟机中执行关闭 SELinux 和防火墙的命令,这一步很多人会跳过,结果后面启动 GreatSQL 时各种玄学报错。

setenforce=0 sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config systemctl disable firewalld systemctl stop firewalld

第一行setenforce=0是临时将 SELinux 从 enforcing 模式切换到 permissive 模式,立即生效但不持久;第二行永久修改配置文件,把SELINUX=那一行替换成SELINUX=disabled,重启后依然生效。这里注意原文给的 sed 命令少了引号,实际执行时c后面的替换内容要用单引号包住,否则会报错。我自己写这类命令时一般拆成两步:先setenforce=0保证当前会话可用,再改配置文件保证重启后不再弹回。

关闭 SELinux 的理由在实验报告里写得很实在:数据库进程需要执行文件读写和网络通信这类特权操作,SELinux 的 MAC 机制可能直接拦截,导致 mysqld 起不来或连不上。防火墙则是另一个拦截点,GreatSQL 默认监听 3306 端口,防火墙规则没放行时,本地ss -lntp能看到监听,但远程客户端就是连不上,表现是连接超时而不是拒绝,排查起来很费劲。

2.2 依赖包安装:缺一个包后面都会翻车

依赖包的安装是实验里最容易被忽略的一步。yum 安装失败时提示信息往往不直观,等启动服务才发现缺库文件,回头再补浪费时间。

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 内存管理,MySQL 系数据库在高并发下对内存分配策略敏感;openssl-devel提供 SSL/TLS 支持,涉及加密连接;jemalloc是内存分配器,能有效减少内存碎片,对长时间运行的数据库进程友好;perl-Data-Dumper、perl-JSON、perl-Test-Simple主要是初始化脚本和工具集需要。python2这个包比较特殊,CentOS 7 自带的是 Python 2.7,一些旧版初始化脚本还依赖它,虽然 GreatSQL 8.0 已经不强制要求,但装上可以避免后续工具报错。

我一般会检查一下安装结果,用rpm -qa | grep libaio确认关键包是否真的装上了。yum 的-y参数会自动确认所有提示,如果某个包在源里找不到,yum 会跳过并继续装其他的,所以装完最好回头看一眼输出有没有Error或Nothing to do。

2.3 下载解压与 systemd 服务托管

官方二进制包下载到/usr/local目录后解压,然后手动创建 systemd 服务文件,这一步决定了后续能不能用systemctl start greatsql这种习惯方式管理数据库进程。

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

解压后目录名自带版本号GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal,操作时可以直接用这个路径,也可以做一个软链接指向它,方便后续升级版本。我习惯做/usr/local/greatsql -> /usr/local/GreatSQL-8.0.32-25-*的软链,这样服务的ExecStart路径可以固定。

接下来创建 systemd 服务文件,这是实验里比较关键的一步,因为编译安装的二进制包默认不带启动脚本:

vim /lib/systemd/system/greatsql.service

服务文件的基础内容里要指定ExecStart为mysqld的完整路径,User和Group设为 mysql,加上Restart=on-failure保证进程异常退出时能自动拉起,LimitNOFILE调大到 65535 避免文件描述符不够用。之后执行:

systemctl daemon-reload

这行命令让 systemd 重新加载单元文件,不加的话systemctl start greatsql会提示找不到服务。

2.4 my.cnf 初始化与目录授权

编辑全局配置文件/etc/my.cnf时,核心参数包括basedir指向解压目录、datadir=/var/lib/mysql、port=3306、socket=/var/lib/mysql/mysql.sock,还需要设置user=mysql让进程以低权限用户运行。如果datadir目录不存在或属主不对,启动阶段就会报Can't create/write to file之类的错误。

/sbin/groupadd mysql /sbin/useradd -g mysql mysql -d /dev/null -s /sbin/nologin 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

创建 mysql 系统用户时指定-d /dev/null和-s /sbin/nologin,意思是该用户不能登录 shell,只用于进程权限隔离,这是一个安全习惯。chown -R把数据目录、日志目录和安装目录的属主统一改成 mysql,缺一步都会导致 mysqld 启动时无法写文件。

初始化数据目录这一步原文没有展开,实际操作时通常需要先执行:

/usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal/bin/mysqld \ --initialize-insecure --user=mysql

--initialize-insecure会生成一个无密码的 root 账号,方便实验环境首次登录,生产环境建议用--initialize让它生成随机密码。

2.5 启动验证:三行命令确认服务状态

启动和验证是检验前面所有配置的收口动作:

systemctl start greatsql systemctl status greatsql ps -ef | grep mysqld ss -lntp | grep mysqld ls /var/lib/mysql

systemctl status只能看到服务是否 active,真正要看的是ps -ef里有没有mysqld进程,以及ss -lntp里 3306 端口是否处于 LISTEN 状态。ls /var/lib/mysql是确认初始化是否生成了系统表空间和mysql.ibd等文件。如果进程起来了但端口没监听,大概率是 my.cnf 里port参数没生效或 SELinux 没关干净;如果/var/lib/mysql下面只有一个空目录,说明初始化步骤被跳过了。

3. 建库建表与索引:把 SQL 定义语句变成可复用模板

3.1 创建数据库与基础表

实验二的目标很直接:用 SQL 语句把数据库、三张基本表和索引全部建出来。第一步创建库并切换:

CREATE DATABASE DB; SHOW DATABASES; USE DB;

这个库名DB是教材里惯用的示例名,实际项目中库名建议用业务英文缩写。SHOW DATABASES用于确认创建成功,USE DB把当前会话切到目标库,后续建表语句都基于这个库。

建表的原始版本如下(注意 SC 表第一版写法里混入了中文逗号,后面再细说):

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 );

这个版本是演示用的极简结构。实验真正要求的是符合教材示例的完整表结构:STUDENTS 表包含学号、姓名、性别、出生日期、专业、系号;COURSES 表包含课程号、课程名、学时、学分;SC 表是选课关系表,主键由学号和课程号联合构成。

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) );

这里有几个参数选型值得说明:学号和课程号用CHAR(9)、CHAR(5)而不是INT,因为这类编号通常是固定长度字符串,前面补零的学号如果用整数存会丢失前导零;Sname和Cname都加了NOT NULL,姓名不该为空;SC 表的主键是复合主键(Sno, Cno),这是选课关系表的经典设计——同一学生选同一门课只能有一条记录,复合主键在约束层面就挡住了重复插入。

3.2 插入实验数据与删除重建

建表之后填充数据,验证表结构是否合理:

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);

注意第三条 SC 记录的学号201705003在 STUDENTS 表里并不存在,这是原文数据里的一个明显疏漏。如果 SC 表定义了外键,这条 INSERT 会直接报外键约束失败。实验一阶段 SC 表没加外键所以能插进去,到实验三重建表结构时就补上了外键。如果你复现时发现数据插不进去,先检查是不是上一张表没建完整。

删除重建是实验里常见的返工操作。原文用了DROP TABLE students CASCADE,但 MySQL 系(GreatSQL 属于 MySQL 分支)并不支持DROP TABLE ... CASCADE语法,8.0 版本会直接报语法错误,正确写法就是DROP TABLE 表名或一次性多个表用逗号分隔。这是实验报告里一个容易让新手卡住的地方:照着教材(偏向标准 SQL)写CASCADE,在 GreatSQL 里就跑不通。

3.3 索引创建与删除:普通索引和唯一索引的差异

索引部分原文留了不少细节:

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

第一个索引落在Dno(系号)上,属于普通索引,目的是加速按系号过滤学生记录。第二个索引比较讲究:Cno已经定义了主键,主键本身就会自动建一个唯一索引,再叠加CREATE UNIQUE INDEX实际上是冗余的,但教材为了演示唯一索引的语法,特意让学生建一遍再删掉。DROP INDEX Course_Cno ON Courses是 MySQL 系的删除语法,标准 SQL 的写法是DROP INDEX Course_Cno,这里需要你记住 GreatSQL 的写法是必须带ON 表名。

实验报告里对索引的总结提到了主键约束、外键约束、唯一约束和非空约束,这些约束在 InnoDB 引擎下的实现方式不同:主键和唯一约束会自带索引,非空约束只是检查层限制,外键约束需要父表对应列有索引。理解这一点,后面建表时就不会重复建冗余索引。

4. 交互式 SQL 查询:从单表 WHERE 到集合条件的实战套路

4.1 不带 WHERE 的查询与表达式计算

实验三开始进入交互式 SQL 查询环节,表结构比实验二更完整,增加了 Departments、Teachers、Teaches 三张表,并且用ALTER TABLE把外键关系补上了。第一类查询不需要条件过滤:

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

第一条是查全表,实验报告里展示的是最直接的SELECT *,实际工作中我建议明确列出字段名,可读性和维护性都好很多。第二条是带表达式计算的查询:YEAR(Birthday)从日期里取出出生年份,再用2024减去,输出时用AS Age把计算列命名为 Age。这里有个小坑:2024是写死的当前年份,如果这条语句在 2025 年再跑,年龄就会全错一年。正确做法是用YEAR(CURDATE())动态取当前年份,这也是实验报告里没体现但值得修正的地方。

4.2 带 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;

第一条查讲师名单,WHERE Title = '讲师'是等值匹配。第二条查不及格学生的学号,Grade < 60是范围过滤,DISTINCT去重很关键——一个学生可能有多门课不及格,不上DISTINCT会输出重复学号。第三条和第四条是BETWEEN与NOT BETWEEN的对称写法,查询 1997 到 1999 年出生的学生,BETWEEN在 MySQL 里是闭区间,包含起止年份。YEAR(Birthday)函数在 WHERE 子句里使用会导致该列上的索引失效,这个数据量下问题不大,但数据量大时应该在条件右侧处理参数值而不是对字段套函数。

4.3 IN 与 NOT IN:集合匹配的两种姿势

集合查询是实验中另一个重点:

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

IN的本质是多个等值条件的缩写,Speciality IN ('计算机', '软件工程')等价于Speciality = '计算机' OR Speciality = '软件工程'。NOT IN则是取反,查这两个专业之外的学生。用IN时要注意列表里不能有 NULL,否则结果集会为空,这是 SQL 三值逻辑里最容易踩的坑——NOT IN (NULL)的结果不是真而是 UNKNOWN,整条查询返回空。规避办法是写NOT EXISTS子查询或确保列表无 NULL。

4.4 补全外键:ALTER TABLE 的收尾操作

实验三建完六张表后,还要用 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);

这几条语句把 Teaches 表的 Cno 关联到 Courses 的 Cno,Tno 关联到 Teachers 的 Tno,把 Students 和 Teachers 的 Dno 关联到 Departments 的 Dno。执行时有一个顺序问题:必须先建父表(Departments、Teachers、Courses),再建子表(Students、Teaches、SC),否则外键引用的父表不存在,语句直接报错。另一个细节是 Teaches 表原文插入的数据里TCsores字段是拼写错误的(应为 TCores 或 Score),但该字段没有实际参与查询,不影响实验流程。

ALTER TABLE 补外键这种做法在日常开发里不算推荐范式——建表时就该把外键写进去,实验里故意拆成两步是为了让学生理解外键约束可以后置添加。但后置添加外键会先扫描一遍现有数据,如果表中已有违反约束的记录,ALTER 会执行失败并给出报错。

5. 避坑:部署和实验中最容易翻车的五个细节

5.1 现象:systemctl start greatsql 启动失败,服务一直处于激活失败状态

原因:最常见的是/var/lib/mysql目录属主没改对或数据目录没初始化。chown -R mysql:mysql漏掉/var/lib/mysql时,mysqld 进程无法在数据目录里创建文件;另一种情况是跳过初始化步骤直接启动,数据目录为空。

解决:先看错误日志,默认路径是/var/log/mysql-error.log或 my.cnf 里log_error指定的文件。确认目录属主后用chown -R mysql:mysql /var/lib/mysql修正;如果没初始化,用mysqld --initialize-insecure --user=mysql重新初始化,再执行systemctl start greatsql。

5.2 现象:启动成功但 3306 端口没有监听,或者本地能连远程连不上

原因:SELinux 没关干净是最常见的元凶。实验里第一条命令setenforce=0只对当前会话生效,如果配置文件没改(或 sed 命令写错了),重启后 SELinux 恢复 enforcing,mysqld 的端口绑定和网络访问被拦截。防火墙没关时,本地通过 socket 连接没问题,但远程 IP 的 TCP 连接被 drop。

解决:执行getenforce确认返回Permissive或Disabled;检查/etc/selinux/config里是不是真的SELINUX=disabled。防火墙用systemctl status firewalld确认是 inactive。最后ss -lntp | grep 3306看端口是否 LISTEN。

5.3 现象:CREATE TABLE 时外键约束创建失败,报 Can't create table 错误

原因:父表和子表的字段类型不一致,或父表对应列上没有索引。比如 Departments 表的 Dno 定义为CHAR(4),Students 表的 Dno 定义为CHAR(4),类型一致才能建外键;如果一个是VARCHAR(20),外键直接失败。父表列如果没建索引,MySQL 也拒绝加外键。

解决:统一两边的字段类型和长度。父表关联列必须有索引,主键自带索引,非主键列要先CREATE INDEX再建外键。我习惯建表时直接在子表定义里写FOREIGN KEY,一步到位,避免后补时踩类型不一致的坑。

5.4 现象:DROP TABLE 后重建失败,报外键约束相关错误

原因:表之间外键依赖没理清。比如直接DROP TABLE Students,但 SC 表还有外键引用它,数据库会拒绝删除或在某些模式下报错。原文里用的DROP TABLE ... CASCADE在 GreatSQL 里不支持,容易误导。

解决:先删子表再删父表,顺序是 SC、Teaches 这类带外键的表先删,最后删 STUDENTS、COURSES、Departments。如果只想删父表,也要先DROP掉子表或先ALTER TABLE ... DROP FOREIGN KEY解除关系。

5.5 现象:INSERT 中文数据后查询乱码

原因:客户端连接字符集和表字符集不一致。CentOS 7 终端默认可能是 utf8,而 my.cnf 里没显式设置character_set_server=utf8mb4,结果数据以 latin1 存进去,查出来直接乱码。

解决:my.cnf 的[mysqld]段下加character_set_server=utf8mb4,重启服务。建表时也可以显式指定DEFAULT CHARSET=utf8mb4。实验里还有个低级但常见的错误是 CREATE TABLE 语句里混入中文逗号(id int,cid int),SQL 解析器直接报错,这类问题排查时先看语句里的标点符号。

6. 实验报告的截图与排版规范:让报告一次通过的检查清单

实验报告原文对提交格式提了明确要求:电子版打印时截图下方要有图的编号和图题,表格上方要有编号及表名,内容要符合书面行文和排版要求。这一章把这些规范整理成可直接对照的检查清单。

先说图的部分。报告里的截图不是随便贴,每张图都要有编号和图题,格式是“图 1 创建数据库”这样的结构,编号按出现顺序递增,图题放在图的正下方,和正文里“如图 1 所示”的引用对应。截图本身要清晰,能看出命令和输出结果,不能只截半个终端。我在整理时一般会把命令行的提示符裁掉,只保留命令区和结果区,图题写明这张图验证了什么,比如“图 5 创建索引 Student_Dept”,阅卷老师不用猜。

表格部分的规范更严格:表上方要有编号和表名,写成“表 1 STUDENTS 表结构”这种格式;表内由属性行和数据行组成,属性行就是列名,数据行是实际内容。用SHOW CREATE TABLE或DESC STUDENTS的输出做表的素材时,记得把无关的引擎信息删掉,只保留字段名、类型、约束这几列,信息密度比直接贴原始输出高得多。

排面上,段首缩进两个字、行文用书面语、内容按逻辑顺序走,这三条是硬性要求。段首缩进在 Word 里用首行缩进 2 字符实现,不要用空格硬顶;书面语意味着实验过程不能写成流水账,比如“遇到数据库无法启动”比“数据库挂了”更符合报告语境;逻辑顺序则要求从环境准备到执行到分析一步接一步。报告的最后一节通常写“问题及总结”,原文在这个部分会列出几条注意事项,比如用正确的数据类型、每个表要定义主键、删除表前先备份数据,这些内容比单纯贴代码更能体现你对实验的理解。

我个人的习惯是每做完一个实验,就把遇到的问题和解决命令追加到一个文本文件里,等最后统一排版时再润色成书面语。这个临时记录不需要讲究格式,但真实还原了踩坑过程,写总结时不会没素材。从那以后,我每次整理实验报告都会强制走一遍检查清单:先核对全文的图编号是否连续,再确认表编号和表名齐全,最后扫一遍有没有混用中英文标点。这份检查习惯,就是实验报告最实用的后悔药。希望这份拆解和坑位整理能帮到你。

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

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

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

立即咨询