资讯详情

资讯详情

GreatSQL数据库原理实验:部署、建表、查询与避坑全流程

简介郑州大学计算机与人工智能学院《数据库系统原理》课程实验报告适合数据库初学者、正在完成同类实验的高校学生及复习备考者。报告完整记录了数据库原理实验的关键环节重点展示万里数据库GreatSQL在CentOS虚拟机中的安装、配置与使用流程包括关闭SELinux和防火墙的原因与命令、依赖包安装、二进制包下载解压、mysql系统用户及系统服务创建、启动与状态检查等并配有进程、TCP连接、数据库文件等截图和命令说明。内容还覆盖数据库系统逻辑组件基本表、视图、触发器、存储过程、约束与物理组件的理解以及实验报告撰写规范如截图需带编号图题、表格需编号表名等可帮助读者规范完成课程实验。压缩包仅含1个docx文档大小3.69MB结构紧凑便于阅读已有509人学习特别适合作为课程实验的环境搭建参考和排错思路借鉴。1. 说到数据库原理实验报告这套 GreatSQL 实验的练习远不止交差数据库原理课程的实验报告很多人的第一反应是“把教材上的 SQL 跑一遍截图贴上去”。但这套实验包的价值比交差要大不少它把环境配置、建库建表、索引管理、交互式查询和报告排版全部串成了一条可复现的路线。前三个实验从安装一个基于 MySQL 8.0 内核的国产数据库发行版起步再到创建 STUDENTS、COURSES、SC 三张表最后把 WHERE、IN、BETWEEN 这些查询条件逐条跑通报告规范里还专门强调了截图编号、表格编号和书面语表达。对于正在赶实验报告、不想在命令行里来回翻车的同学这套资料的命令可以直接抄对于想脱离图形界面、通过终端理解数据库管理系统的初学者它也是一份从零到查询的完整走查记录。2. 环境搭建为什么要关 SELinux以及数据库二进制包的正确安装方式2.1 安全策略的取舍SELinux 和 firewalld 为什么必须处理安装文档的一开始就出现了setenforce0和systemctl stop firewalld两条命令。很多第一次接触 Linux 数据库部署的人会疑惑数据库运行和安全策略冲突吗答案是会冲突尤其在 CentOS 7 这种默认开启 SELinux 的系统上。SELinux 是强制访问控制机制它给文件、进程、端口都打上了安全标签。数据库服务启动时要读取/etc/my.cnf、写入/var/lib/mysql、绑定 3306 端口这些操作如果和 SELinux 的进程域不匹配mysqld就可能出现权限拒绝。表现五花八门有时候是启动后立即退出有时候是能启动但无法创建 socket 文件。关闭 SELinux 不见得是最优解但在教学环境里它能把变量控制到最小让后续实验的精力集中在 SQL 本身。防火墙同理——默认的 firewalld 区域不会放行 3306 端口如果后面要使用图形化客户端做远程连接端口不通会让人误判为服务没起来。这里要特别提醒setenforce0只对当前运行状态生效重启系统后 SELinux 会回到 enforcing。真正要永久关闭必须修改/etc/selinux/config。实验报告里给的那条sed命令就是做这个的它把配置文件中以SELINUX开头的行整体替换成了SELINUXdisabled。setenforce0 sed -i /^SELINUX/cSELINUXdisabled /etc/selinux/config systemctl disable firewalld systemctl stop firewalld命令说明第一行立刻把 SELinux 切换到 permissive 模式相当于临时放开限制第二行持久化修改配置防止重启后失效第三行disable让 firewalld 不再开机自启第四行stop立即关闭防火墙。实际工作中如果只是想临时测一下只执行第一和第四行就够了但在实验环境里两条都要写否则下次开机又会被安全策略拦住。2.2 依赖包清单与二进制解压每个参数都在解决什么问题在下载二进制包之前先要解决依赖库。数据库发行版虽然自带大部分运行库但 glibc 环境下的部分扩展库还需要系统提供。实验里给出的依赖安装命令是这样的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 存储引擎的读写操作会用到它缺失时可能导致初始化失败jemalloc是内存分配器官方二进制包推荐用它提升内存分配效率numactl-devel和numactl-libs用于 NUMA 架构下的 CPU 内存绑定多核服务器上对性能有影响perl-Data-Dumper和perl-JSON是数据库自带运维脚本的运行依赖。如果是最小化安装的 CentOSyum源里可能没有这些包需要先执行yum install -y epel-release扩展软件源。依赖装完后进入下载和解压阶段。实验选择的是官方预编译二进制包而不是源码编译。二进制包的好处是解压即用不需要经历漫长的cmake和make过程缺点是对系统环境敏感所以前面那串依赖必须装齐。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下载链接指向的是 8.0.32-25 版本的 minimal 最小化安装包。冠以 glibc2.17 表示它可以在 CentOS 7 的默认 glibc 版本下运行。tar xf不需要加-z因为.xz解压由xz工具处理CentOS 7 默认已经自带了。解压完成后/usr/local/下会出现对应版本的目录后面启动服务就是指向这个目录里的bin/mysqld。接着是创建 mysql 系统用户和数据目录。数据库服务不允许直接以 root 身份运行这是安全底线。mysql用户不分配登录 shell只用于运行守护进程/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-minimalchown -R将数据目录、日志目录和安装目录都归属给 mysql 用户。如果漏掉这一步mysqld启动时无法在/var/lib/mysql下创建系统表文件会直接报 “Permission denied”。这类错误非常隐蔽因为命令执行时本身不会提示。2.3 服务注册到 systemd启动、状态检查和常见失败定位二进制包不会自动生成 systemd 服务文件需要手动创建一个。这个文件把数据库进程交给 systemd 托管之后就能用systemctl start/stop/status来管理不需要每次手敲mysqld_safe。vim /lib/systemd/system/greatsql.service服务文件的核心内容如下[Unit] DescriptionGDB Server Afternetwork.target [Service] Usermysql Groupmysql ExecStart/usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal/bin/mysqld LimitNOFILE65535 [Install] WantedBymulti-user.targetUsermysql和Groupmysql指定进程以哪个身份运行和前面创建的用户对应。Afternetwork.target表示网络服务就绪后再启动数据库避免监听端口时网络还没准备好。LimitNOFILE65535把文件描述符上限调大数据库并发连接高时会创建大量 socket 和文件句柄默认 1024 的限制很容易触顶。写完服务文件后必须执行systemctl daemon-reloadsystemd 才会重新读取配置文件。之后启动数据库systemctl start greatsql systemctl status greatsql ps -ef | grep mysqld ss -lntp | grep mysqld ls /var/lib/mysqlsystemctl status能看到服务是否处于 active 状态、进程 PID 以及最近的日志输出。ps -ef | grep mysqld检查进程是否真实存在如果只显示 grep 自身说明服务启动后崩了。ss -lntp | grep mysqld确认 3306 端口在监听。最后列一下/var/lib/mysql数据目录如果里面有mysql.ibd、ibdata1这些初始化文件说明首次启动已经完成了系统库初始化。启动之前还应该检查/etc/my.cnf是否存在。如果文件缺失mysqld会使用编译时默认配置数据目录可能指向/var/lib/mysql以外的位置。常见的做法是最少写上三段配置[mysqld] datadir/var/lib/mysql socket/var/lib/mysql/mysql.sock port3306 character-set-serverutf8mb4character-set-serverutf8mb4这一行非常关键。默认字符集在旧版本里可能是latin1插入中文时命令行显示会变成乱码排序规则也会受影响。实验环境里如果一开始没配后面建表时每个字段都得手动指定字符集非常麻烦。如果服务启动失败第一件事是执行journalctl -u greatsql -n 50看日志不要盲目重启。常见的失败原因就三类数据目录权限不对、配置文件里的路径不存在、依赖库缺失。3. 建库建表建索引从逻辑设计到物理文件都要讲清楚3.1 创建数据库 DB以及数据页、表空间这些物理概念实验二的第一步是创建一个名为 DB 的数据库。这个操作在原理上很简单但它带出了一个值得深挖的问题数据库文件到底存在哪里CREATE DATABASE DB; SHOW DATABASES; USE DB;在 MySQL 系列的存储引擎里CREATE DATABASE做的事情是在数据目录下创建一个同名子目录。默认数据目录由/etc/my.cnf里的datadir指定通常是/var/lib/mysql。执行完上面三条命令后可以到系统里确认一下ls /var/lib/mysql | grep -i db如果能看到一个名为db的目录说明数据库创建成功。这个目录在初始化时是空的后续创建的表会以独立文件的形式出现在这里。InnoDB 引擎的表会同时生成.ibd文件存放数据行和索引表结构则记录在数据字典中。物理存储的单位是数据页默认大小通常是 16384 字节。数据页是 InnoDB 从磁盘读取和写入的最小单位一页里可能存放多行数据也可能一个表有几百个页。理解数据页的意义在于为什么查询走索引比全表扫描快本质上就是减少了需要读取的数据页数量。实验报告里如果能写一句“数据以数据页存储表对应一个或多个页文件”这部分的得分点基本就拿到了。3.2 STUDENTS、COURSES、SC 三张表字段类型为什么这么选建表的第一个版本非常简单id int primary key这种结构适合快速演示但不符合教材的语义需求。实验里从简版改成正式版这一步是理解字段类型的好机会。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)而不是int是因为学号是编号而非数值它不需要参与加减乘除而且用字符类型可以保留前导零以后如果出现类似“001”的编号也不会丢失信息。Sname 加NOT NULL姓名不应该为空。Sex 用char(2)教材里的取值只有“男”和“女”两个汉字。Birthday 用DATE类型而不是字符串这样后续可以使用日期函数做年龄计算。SC 表的主键是(Sno, Cno)复合主键因为一个学生选一门课的成绩记录需要学生和课程两个维度才能唯一确定。在正式创建三张表之前实验里先演示了删除操作DROP TABLE students CASCADE; DROP TABLE courses CASCADE; DROP TABLE sc CASCADE;实际上 MySQL 的DROP TABLE并不支持CASCADE关键字这是 Oracle 数据库的写法。如果直接复制到命令行里执行会报语法错误。正确写法是直接DROP TABLE 表名。这个问题也提醒了一件事教材里的 SQL 不能无脑照抄需要根据具体的数据库产品调整。填充数据是建表后的必做步骤。这里要注意插入顺序——先插入父表再插入子表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 表的插入数据里只有201705001、201705002和201706001没有201705003。如果在创建 SC 表时同时定义了外键约束这条插入就会直接违反外键约束返回Cannot add or update a child row。教材数据里这种不一致很常见实验时要么把 STUDENTS 表补上对应学号要么去掉外键约束再插入。这个细节后面避坑章节还会展开。3.3 索引普通索引、唯一索引与删除操作索引是数据库原理实验的必考内容。实验要求在 Students 表的 Dno 字段上创建普通索引在 Courses 表的 Cno 字段上创建唯一索引CREATE INDEX Student_Dept ON Students (Dno); CREATE UNIQUE INDEX Course_Cno ON Courses (Cno);普通索引声明的语义是“允许重复值”它只加速查询不约束数据。Dno 是院系编号一个系有多个学生所以这里用普通索引合适。唯一索引的语义是“字段值不能重复”Cno 本来就是主键主键本身已经隐含唯一索引这里再创建一个唯一索引属于锦上添花主要演示UNIQUE关键字。删除索引的语法和 Oracle 不同MySQL 使用DROP INDEX 索引名 ON 表名DROP INDEX Course_Cno ON Courses;删除后可以再次执行SHOW INDEX FROM Courses;验证索引是否移除。这里有一个设计上的问题值得思考主键和唯一索引都能保证唯一性为什么还需要主键主键是表的逻辑标识每行数据必须有且只有一个唯一索引只是业务约束不一定是行的身份标识。索引不是越多越好每个索引在加速查询的同时都会拖慢插入和更新操作因为写入数据时所有索引都需要同步维护。这种“读写权衡”的观念实验报告的分析部分可以写进去。最后处理表间约束。SC 表中的 Sno、Cno 分别引用 Students 和 Courses正确做法是在建表后用ALTER TABLE补上外键ALTER TABLE SC ADD CONSTRAINT fk_sc_sno FOREIGN KEY (Sno) REFERENCES Students(Sno); ALTER TABLE SC ADD CONSTRAINT fk_sc_cno FOREIGN KEY (Cno) REFERENCES Courses(Cno);但这里有个执行前提SC 表里的 Sno 和 Cno 值在父表里必须已经存在。如果上面插入的 SC 数据里有201705003而这个学号在 Students 表里不存在这条ALTER TABLE会直接失败。所以遇到外键约束添加失败不要怀疑语法先查数据完整性。4. 交互式 SQL 查询把教材上的 WHERE、IN、BETWEEN 跑成自己的数据4.1 全部查询与计算字段不带 WHERE 的简单场景实验三的第一步是先建好完整的数据表再开始各种查询。不带 WHERE 的查询最简单但里面也藏着一个小知识点——计算字段。SELECT * FROM Courses; SELECT Sname, 2024 - YEAR(Birthday) AS Age FROM Students;第一条查询返回 Courses 表的全部列没有任何过滤条件执行计划里走的是全表扫描。第二条查询里YEAR(Birthday)从日期字段中提取出生年份然后用当前年份减去它得到年龄。这里有个隐患如果系统当前时间不是 2024 年算出来的年龄就是错的。更严谨的做法是用TIMESTAMPDIFF(YEAR, Birthday, CURDATE())它会自动根据当前时间计算精确年龄。SELECT Sname, TIMESTAMPDIFF(YEAR, Birthday, CURDATE()) AS Age FROM Students;TIMESTAMPDIFF是 MySQL 系列的日期差函数第一个参数指定单位第二个参数是起始日期第三个参数是结束日期。这个函数的好处是不用硬编码年份每年的结果都正确。实验报告里如果写“计算字段可以用 YEAR 函数也可以用 TIMESTAMPDIFF 更严谨”体现的思路会让报告加分。4.2 条件查询等于、小于、范围与 NOT 的组合带 WHERE 的查询是交互式 SQL 的核心。实验里要求按教材完成多个查询实例这里挑几个典型写法拆解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 讲师用了字符串等值比较。中文引号会导致语法错误这里必须用 ASCII 单引号。第二个查询用DISTINCT去重查出所有考试不及格的学生学号如果不加DISTINCT同一个学号挂科多门课会出现多行。对于实践报告提醒不及格课程多门时用DISTINCT很实用。第三和第四条是范围查询。BETWEEN 1997 AND 1999是闭区间等价于 1997 AND 1999NOT BETWEEN取反。这个写法比手写两个比较条件更清晰。注意YEAR(Birthday)函数把日期转成年份再做比较这是对字段套函数如果 Birthday 列上有索引套函数会导致索引失效全表扫描。数据量小无所谓但如果到了几十万行的场景应该改成Birthday 1997-01-01 AND Birthday 2000-01-01让索引能发挥作用。接下来是 IN 条件SELECT Sno, Sname FROM Students WHERE Speciality IN (计算机, 软件工程); SELECT Sno, Sname FROM Students WHERE Speciality NOT IN (计算机, 软件工程);IN 列表本质是多个 OR 条件的简写。NOT IN需要注意 null 陷阱——如果被比较列里有 NULL 值NOT IN的结果可能不符合直觉它会对 NULL 返回 UNKNOWN导致整行被过滤掉。在实验数据较少时不容易暴露但在真实数据里很容易让人困惑。4.3 更新操作插入、修改、删除时容易被忽略的细节教材的更新操作分三类插入、修改、删除。实验报告要求关注标准 SQL 和 M 系数据库 SQL 的差异。这里有一个最重要的差异就是前面提到的DROP TABLE ... CASCADE标准 SQL 支持而 M 系数据库不支持。UPDATE Students SET Sname 张华 WHERE Sno 201705001; DELETE FROM SC WHERE Grade 60; INSERT INTO Students(Sno, Sname, Sex, Birthday, Speciality, Dno) VALUES (201705004, 王芳, 女, 2000-03-15, 计算机, CS);UPDATE 语句必须带上 WHERE否则会更新整张表的全部行这是最容易翻车的操作。经验做法是先写 WHERE再回头补 SET确保过滤条件明确。DELETE 同理不带 WHERE 会清空整张表而且这个操作不可回滚——除非事务里已经执行了START TRANSACTION。插入语句列出字段名比不列字段名更清晰也更能避免字段顺序变化导致的数据错位。5. 实验过程中的避坑清单五个真实报错与对应解法5.1 现象服务启动失败且日志提示权限不足执行systemctl start greatsql后服务一直是 failed 状态。journalctl -u greatsql -n 50里出现Permission denied或Cant open file /var/lib/mysql/ibdata1。原因只执行了setenforce0没有在/etc/selinux/config里把 SELINUX 改为 disabled。第一次启动时 SELinux 被临时关闭一切正常重启系统后 SELinux 恢复 enforcing数据目录写入被安全策略拦截。另一个可能原因是mysql用户没有数据目录的写权限因为chown -R那步被跳过了。解决检查/etc/selinux/config是否真的是SELINUXdisabled检查/var/lib/mysql的属主是否为 mysql:mysql。两个条件都满足后再systemctl start greatsql。从那以后我每次装数据库都会先跑一次getenforce确认状态而不是想当然以为关过了。5.2 现象日期数据插入后查询不到结果插入 Birthday 字段时用了1999_12_16这种下划线分隔的格式INSERT 成功了但WHERE Birthday 1999-12-16查不到。原因M 系列数据库默认启用了严格模式日期字符串必须符合YYYY-MM-DD格式。下划线格式在某些版本里会被解析为 0 值日期或者直接报Incorrect date value错误。这条记录很可能根本没插入或者被存成了全零日期。解决统一使用1999-12-16这种标准格式。如果表里已经混入了全零日期先执行SELECT * FROM Students WHERE Birthday 0000-00-00定位数据再手动修复或删除。5.3 现象学号字段用了 int 导致输出不符合预期建表时把 Sno 定义成int插入201705001后查询结果变成了201705001看起来没问题但如果学号是0001这种前导零格式存储后直接丢失了 0变成 1。原因int 是数值类型它只保存数值大小不保存格式。前导零不是数值的一部分所以必丢。学号、身份证号、电话号码这类“看起来像数字”但不需要计算的字段都应该用 char 或 varchar。解决把 Sno 改成char(9)已经建表的执行ALTER TABLE STUDENTS MODIFY Sno char(9);。这个坑在实验二里就会遇到建议建表时直接按正式版结构来不要偷懒用 int 简化。5.4 现象SQL 一直报语法错误但看起来没问题复制教材或 Word 文档里的 SQL 执行返回1064 - You have an error in your SQL syntax检查半天发现引号用的是中文全角和。原因很多教材 PDF 或网页里的引号会被排版软件自动转成全角。数据库只认 ASCII 单引号全角引号直接导致语法解析失败。解决写 SQL 时统一在终端或编辑器中输入不要直接复制带格式的文档内容。如果已经报错把引号替换成英文单引号。这个坑非常隐蔽新手排查语法问题往往在括号和关键词上折腾半天实际只是引号字符的问题。5.5 现象外键约束阻止数据插入或 ALTER TABLE 失败插入 SC 表的201705003时报错Cannot add or update a child row: a foreign key constraint fails。或在执行ALTER TABLE SC ADD FOREIGN KEY...时卡住。原因SC 表的 Sno 字段里存在父表 Students 中没有的学号。外键约束要求子表的所有引用值都必须在父表主键中存在否则约束无法通过验证。解决先检查不一致数据执行SELECT SC.Sno FROM SC LEFT JOIN Students ON SC.Sno Students.Sno WHERE Students.Sno IS NULL;找出孤立记录后要么在父表补插入对应学生要么删除这些子表记录然后重新执行 ALTER TABLE。这个顺序问题是数据库设计里的经典场景所有外键约束的添加顺序都应该是先父后子。6. 把实验过程变成一份规范报告编号、截图和表题的固定套路6.1 截图下方必须有图编号和图题实验报告的要求里反复出现一条截图下方需要有图的编号和图题。这听起来很简单但很多人交上去的报告里只有“图1”“结果如下”这种敷衍写法。规范的格式是“图1 创建数据库结果”图编号用阿拉伯数字按顺序排图题应该概括这张图表的内容而不是写“运行截图”。截图要裁剪干净只保留和当前操作相关的窗口区域不要整张桌面糊上去。6.2 表格上方那行“表1 学生表”不是可选项报告里如果有数据展示比如 SC 表的部分数据应该在表格上方写“表1 选课成绩表”下面才是属性行和数据行。属性行就是列名 Sno、Cno、Grade数据行是具体记录。表格编号和图编号分开计不要混用“图 1”“表 1”的时候编号串在一起。这个格式要求看似是排版细节数据库课程设计里往往是很容易被扣分的一项。6.3 报告正文里的“过程→问题→更正→分析”顺序写实验报告最容易犯的毛病是只贴一段 SQL 加一张截图完全没有过程描述。规范的做法是先用一到两句话说明本步要做什么再贴出核心命令然后写执行过程中遇到的问题、如何排查和更正最后写出结果并分析原因。比如在安装数据库的环节报告里可以写“关闭 SELinux 和防火墙是为了避免安全策略限制数据库端口监听”而不是光写两行命令。我的习惯是每次实验过程中开一个临时目录把每一步的关键报错截图和纠正命令单独存下来写报告时照着这个素材库整理。这样既不会漏掉过程也不会在截图编号上翻车。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →