
简介这是一份郑州大学计算机与人工智能学院《数据库系统原理》课程的实验报告文档适合郑大计算机类学生及需要完成GreatSQL环境搭建与数据库管理系统实验的初学者参考。报告完整覆盖了从认识DBMS系统、配置VMwareCentOS运行环境、关闭SELinux与防火墙、安装依赖包到部署万里数据库GreatSQL、管理服务与查看逻辑/物理组件等环节并配有实验截图、命令解释、结果分析与问题反思。资源为1个docx文件压缩包大小约3.69MB内容可直接对照翻阅或作为报告撰写格式范本。已有509人学习下载尤其适合在实验任务中快速定位安装命令、理清实验步骤和规范化呈现实验截图与表格的同学。1. 数据库实验的第一关装了 SELinux 的系统数据库为什么“失语”做数据库原理实验多数人以为最大的坎是 SQL 写不对真正卡住他们的往往是环境配置。一份数据库实验报告的第一个操作不是 CREATE TABLE而是一行setenforce0和一次防火墙禁用。这个动作看起来像“偷懒”背后其实是 SELinux 的强制访问控制MAC机制会拦截数据库进程的文件读写与网络通信让它明明启动着却对外“失语”。搞懂这一步等于拿到了理解整个 DBMS 的钥匙数据库要文件、要端口、要特权操作而这些恰恰都是安全机制默认不放行的东西。这也是为什么这份实验报告的安装部分读起来像系统课——它逼着你从进程的视角看待一个数据库的生存条件。2. 安装链路拆解二进制包、最小权限用户与 systemd 的同一个目标这一步实验的目标不是“把 SQL 跑起来”而是先把 mysqld 变成一个可控的系统服务。很多人把下载解压后的启动失败归结为玄学实际上整条链路——依赖包选择、用户创建、服务文件注册、全局配置文件——都在围绕同一件事让数据库进程以正确的权限、正确的库、正确的方式运行。拆开看每个步骤背后都有明确的设计意图。2.1 glibc 2.17 和那串依赖包二进制包并不是“免安装”实验下载的是GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal.tar.xz。这个文件名里信息量很大glibc 2.17 意味着二进制是在 CentOS 7 的 libc 版本下编译的直接决定了它能跑在什么系统上minimal表示精简安装不含客户端全家桶只保留服务端核心。但“二进制包”不等于“免安装”——它只省去了编译运行时的动态库依赖一个都不能少。实验里的这条命令决定了 mysqld 能不能正常拉起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是 InnoDB 原生异步 IO 的基础数据库刷盘不能靠同步等待磁盘numactl-devel提供 NUMA 感知能力MySQL 的大缓冲池场景最怕内存跨节点访问绑定 NUMA 能显著减少远端内存延迟jemalloc则是把 glibc 默认的内存分配器替换掉多线程高并发下 glibc malloc 的锁竞争和内存碎片是出了名的痛点jemalloc 用 arena 分片把分配压力摊开。perl-JSON、perl-Test-Simple这些看起来八竿子打不着它们是管理脚本的运行时依赖。所以这串依赖不是“多点几个包没关系”而是每一个都对应一个运行时行为。2.2 mysql 用户没有家目录最小权限的边界设计安装流程里有一段很容易被跳过的操作/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/-d /dev/null表示不为这个用户创建家目录-s /sbin/nologin表示这个用户永远无法登录 shell。为什么要这么“苛刻”数据库进程本身只需要一个能标识文件属主的 uid不需要任何交互能力。凡是能登录的用户都会扩大攻击面——一旦数据库被注入或文件权限配置失误攻击者能拿到的只是一个无法登录的账号而不是一个 shell。接下来的chown -R mysql:mysql /var/lib/mysql/是启动的前提。mysqld 在初始化数据目录时会检查目录属主属主不是当前运行用户就直接拒绝工作。这一步如果做错后续systemctl start会看到服务“启动即失败”错误日志里全是权限相关报错。所以数据目录的属主必须和进程用户严格一致这是数据库部署里最容易踩的坑也是最容易排查的坑。2.3 systemd 服务与 my.cnf托管生命周期而不是手动启停把二进制解压到/usr/local之后还需要让系统“认识”这个数据库。实验用了一个非常标准的做法写 systemd 服务文件。[Unit] DescriptionGreatSQL Server Afternetwork.target [Service] Typesimple Usermysql Groupmysql ExecStart/usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal/bin/mysqld \ --defaults-file/etc/my.cnf LimitNOFILE65535 Restarton-failure [Install] WantedBymulti-user.target写完文件必须执行systemctl daemon-reload否则 systemd 会报Unit not found。这是因为 systemd 在启动时已经把单元文件加载进缓存新增或修改后必须重载才能生效。这一步是新手最容易卡住的地方——文件明明写对了服务就是起不来。my.cnf是全局配置文件关键项包括datadir数据目录、socket本地连接套接字、port监听端口、character-set-server默认字符集和log-error错误日志路径。数据目录放哪里本质就是配置文件里这一个路径决定这也呼应了后面“查看数据库物理存储位置”的实验目的。启动之后实验要求用三条命令做三层验证这个习惯非常好systemctl status greatsql ps -ef | grep mysqld ss -lntp | grep mysqldsystemctl status看的是服务状态ps看进程是否存活ss看端口是否真的在监听。这三层必须逐层确认因为服务显示 active 不代表端口已就绪mysqld 在初始化早期、权限出错或启动参数有误时都可能出现“进程活着但没监听”的中间态。3. 逻辑组件与物理存储基本表、视图、触发器之间的虚实边界建表之后数据库里除了“表”还多出一批看不见的东西视图、触发器、存储过程、约束。它们都被记录在information_schema数据字典里这也是实验里大量查询information_schema的原因。理解这一章的关键是分清哪些组件真正占有物理存储哪些只是“定义”。这个区分决定了你对数据库逻辑结构的认知是否准确。3.1 基本表与视图一个占物理页一个只存定义基本表是“实物”——数据行落在表空间的数据页上。视图则是“投影”它不存储数据只保存一条 SELECT 定义每次被引用时动态展开成对底层表的查询。实验里的两条命令放在一起看非常有意思SHOW TABLES; SHOW FULL PROCESSLIST;前者确实能看到包括视图在内的表列表但后者根本不是“查看视图”的命令——它列出的是当前所有连接线程。这是这份实验报告里一个隐蔽的错位后面避坑部分会细说。查视图的正确入口是information_schema.VIEWS里面存着视图名、定义者、字符集和完整的VIEW_DEFINITIONSQL 文本。视图的价值有两个一是把复杂查询封装成“看起来像表”的对象让业务侧只面对简单接口二是做行级或列级的安全隔离比如只暴露学生的姓名和专业不暴露出生日期等隐私列。代价也很直接每次查视图都会重新执行底层 SQL如果视图嵌套多层性能可能不如直接查表。所以视图是逻辑层的“虚表”不是物理层的“复制表”。3.2 触发器与存储过程事件钩子和预编译单元触发器和存储过程都记录在数据字典里。实验用下面两条命令读取它们SELECT * FROM information_schema.TRIGGERS\G SELECT ROUTINE_NAME, ROUTINE_TYPE, CREATED FROM information_schema.ROUTINES WHERE ROUTINE_TYPE PROCEDURE;TRIGGERS表里的关键字段是EVENT_MANIPULATIONINSERT/UPDATE/DELETE、ACTION_TIMINGBEFORE/AFTER、ACTION_STATEMENT触发器体里的 SQL。从数据字典视角看触发器就是一个“事件绑定的钩子”某张表发生指定事件时数据库自动执行一段语句块。它常用于数据一致性维护比如订单删除时联动清理明细或禁止在非工作时间修改核心表。存储过程和触发器在数据字典里是两类不同的对象但有一个共同点都是服务端预编译的 SQL 逻辑。存储过程被封装成独立单元业务只需传参数调用减少客户端与服务器之间的往返触发器则完全由事件驱动业务方甚至感知不到它的存在。这也意味着触发器有隐形成本——它对调用方透明出现问题后排查链路更长写日志、做审计时要格外小心。3.3 约束不是免费的主键、唯一索引与外键的物理代价约束在逻辑层是“规则”在物理层却对应真实的数据结构。实验二的建表语句正好展示了这一点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 UNIQUE INDEX Course_Cno ON Courses (Cno); DROP INDEX Course_Cno ON Courses;主键约束在 InnoDB 里会生成聚簇索引整张表的数据行按主键的 B 树组织唯一约束会生成一个强制键值不重复的二级索引唯一性的检查靠索引结构本身来完成不是逐行扫描比对。外键则更贵——每次插入、更新子表记录时数据库都要去父表检查引用是否存在这背后的锁和事务开销容易被低估。所以建约束时值得多问一句这条规则真的需要数据库来强制还是应用层可以兜底实验里对 SC 表采用复合主键PRIMARY KEY (Sno, Cno)而不是额外的自增 id这正是教科书里的标准做法——业务语义本身就是唯一标识不需要再引入一个无业务含义的代理键。约束是数据完整性的“后悔药”但它不是免费的。4. SQL 执行链路从解析器到数据页一条查询怎么“走”到磁盘实验一要求了解数据库系统架构给出的组件清单是连接池、系统管理与控制工具、SQL 接口、查询解析器、查询优化器、可插拔存储引擎以及系统和日志文件。这些组件不是并列的装饰它们构成了一条完整的执行链路。这一章把这条链路从入口到磁盘走一遍。4.1 数据页为什么物理存储的单位不是“行”而是“页”实验里有一句结论物理存储的存储单位是数据页。这是一个值得展开的机制点。InnoDB 的默认页大小是 16KB表的数据按主键聚簇成 B 树树的叶子节点就是数据页磁盘 IO、缓冲池换入换出都以页为粒度。为什么不用“行”作为 IO 单位因为磁盘的最小寻址和传输成本很高按页读写可以利用空间局部性一次读取就带回相邻的多行后续查询命中缓冲池的概率更高。缓冲池Buffer Pool是 InnoDB 性能的核心它以页为缓存单位脏页由后台线程统一刷盘而不是每条语句实时落盘。理解了这一点就理解了为什么ls /var/lib/mysql看到的是ibdata1、#innodb_redo这样的文件而不是一张表一个 txt——数据文件和内存页之间隔着一整套缓冲与刷盘机制。4.2 六大组件与一条命令的旅程一条 SQL 从客户端到磁盘要顺序经过以下组件组件职责一句话理解连接池管理客户端连接与认证分配线程管理会话状态SQL 接口接收 SQL 语句DML/DDL 的入口通道解析器词法、语法分析生成语法树校验语义优化器生成执行计划决定走哪个索引、什么连接顺序存储引擎读写表数据与索引负责任务、锁、页与事务日志日志文件记录重做与撤销信息redo 保证崩溃恢复undo 支持回滚解析器只负责“看懂”语句不负责“做好”它把 SQL 拆成语法树检查表名、列名是否存在权限是否足够。真正决定性能的是优化器——它会基于统计信息估算代价在“全表扫描”和“走索引”之间做选择。实验里介绍的 MGR组复制位于引擎之上通过 binlog 在节点间广播事务属于高可用层面的能力单机执行链路并不依赖它。4.3 一条 WHERE 查询是怎么走到数据页的实验三有大量查询练习其中一条很典型SELECT Sname, Speciality FROM Students WHERE Year(Birthday) BETWEEN 1997 AND 1999;从执行链路看这条语句先经过解析器生成语法树然后优化器评估访问路径。关键问题在于Year(Birthday)优化器面对被函数包裹的列时通常会放弃该列上的索引——因为 B 树存储的是原始值无法直接对“年份”做范围定位。执行计划会退化成全表扫描即使 Birthday 上建了索引也用不上。执行计划可以用 EXPLAIN 查看典型的退化特征如下------------------------------------------------------------ | id | select_type | table | type | rows | Extra | ------------------------------------------------------------ | 1 | SIMPLE | Students | ALL | 6 | Using where | ------------------------------------------------------------type ALL就是全表扫描。正确的写法是直接让索引可比较SELECT Sname, Speciality FROM Students WHERE Birthday BETWEEN 1997-01-01 AND 1999-12-31;Bloomfield 这样的细节在教材查询里看不出差别但数据量一上来就是几百倍的时间差。实验报告里特别提到 GreatSQL 的 InnoDB 并行查询能把 TPC-H 性能平均提升 15 倍、最高 40 多倍这个提升背后正是优化器把大查询拆给多个 worker 线程并行扫描分区或索引——本质是拿调度开销换大查询吞吐适用于 OLAP 场景和周期性统计。这和执行链路的关系是查询优化不只发生在索引选择这一步已经延伸到引擎层的并行执行策略。提示写 SQL 时把函数套在列上等于主动告诉优化器“这个索引用不上了”。条件写在函数里吃亏的是执行计划。5. 避坑记录SELinux、字符集与级联删除的五类现场这一章是血泪经验。实验报告里明确说“安装过程中没有遇到什么问题”但那些没有被记录下来的错位、误判和隐藏条件恰恰是新手最容易翻车的地方。按“现象 → 原因 → 解决”的格式整理五条。5.1 现象SHOW FULL PROCESSLIST 被当成“查看视图”的命令实验报告在“视图”这一条目下给出的命令是SHOW FULL PROCESSLIST这实际上是查看当前所有连接线程的命令。执行后你会看到一列Command字段里面是Sleep、Query之类跟“视图”没有任何关系。原因是在“查视图”这个操作上抄错了命令没有核对输出内容。解决方法是改用SHOW FULL TABLES WHERE Table_type VIEW或者直接查数据字典SELECT TABLE_NAME FROM information_schema.VIEWS;这个错位不致命但它提醒一件事不是命令执行成功就代表操作正确要养成看输出内容验证的习惯。5.2 现象systemctl start 显示 active端口却没有任何监听服务状态正常、进程存在但ss -lntp | grep mysqld没有输出。常见原因是 mysqld 还处在初始化早期或my.cnf里的port、socket配置被覆盖。另一个隐蔽原因是/var/lib/mysql的属主不是 mysql导致 InnoDB 在打开数据文件时失败。解决路径是看错误日志tail -f /var/log/mysqld.log权限问题会直接在日志里报Permission denied配置问题则会报unknown variable或端口冲突。5.3 现象插入中文数据后查询乱码数据库默认字符集不是 utf8mb4客户端连接时走的又是另一套字符集两端不一致就会在写入和读取时发生编码转换错误。解决方法是统一字符集在/etc/my.cnf里配置character-set-server utf8mb4建库时显式指定CREATE DATABASE DB DEFAULT CHARACTER SET utf8mb4同时保持客户端连接字符集与服务端一致。5.4 现象DROP TABLE students 被外键挡住SC表通过外键引用了Students直接删父表会报外键约束错误。解决办法是先删除引用表或先移除外键约束。这也是为什么实验里第一次执行drop table students cascade会失败——CASCADE是 PostgreSQL 风格的级联删除语法GreatSQL/MySQL 并不支持在 DROP TABLE 时带CASCADE来级联清理引用表。遇到这种情况正确顺序是DROP TABLE SC; DROP TABLE Students;5.5 现象SELinux 一开数据库就“失联”这是第 1 章那个问题的现场版。SELinux 开启时即使 mysqld 进程活着它对数据目录的文件访问也可能被 MAC 策略拦截网络端口也可能无法正常监听客户端连接直接超时。实验选择了关闭 SELinux 和防火墙这是开发环境里最省事的做法——数据库需要文件读写、网络监听和特权操作这些恰好都是安全机制默认不放行的。原因需要理解清楚这不是“Linux 安全机制没用所以关掉”而是“在隔离的虚拟机实验环境里安全策略的收益低于配置成本”。6. 最后的取舍事务锁从红黑树到无锁哈希到底在换什么实验一里提到一个很值得琢磨的改造GreatSQL 把 InnoDB 的事务锁数据结构从红黑树优化成无锁哈希结构。红黑树是平衡二叉搜索树插入、删除、查找都是 O(log n)哈希表在等值查找下接近 O(1)。锁对象查找恰恰是高并发场景下的热路径。我一般会这么理解事务锁的查找本质是“精确匹配”——一个事务要判断自己与哪些已持有锁的事务冲突查的是特定行或特定间隙的锁对象这正是哈希的主场。红黑树虽然支持范围遍历和有序输出但高并发下树旋转和全局结构竞争带来的开销都落在每一次加锁解锁上属于纯成本。换成无锁哈希后查找路径变短并发度上去了事务并行性能随之改善。这个方向落地时还会配合更细分的锁分区避免所有线程挤在同一个锁结构上。但是无锁哈希不是白捡的性能它为等值查找优化牺牲了范围查询能力调试死锁、打印锁等待链时需要额外辅助结构来重建有序视图。这就像把工具箱里的万用扳手换成了成套的专用套筒——常用场景更快了冷门场景则需要另找工具。同一个思路也贯穿在 GreatSQL 对 MGR 的流控优化和大事务检测里都是先识别最痛的热路径再用针对性的数据结构去替换通用方案。从那以后我每次看到某个数据库“特性优化”都会先问三个问题原来是什么结构、换成了什么结构、放弃了什么能力。想清楚这三点性能提升的“为什么”就不再是玄学。希望帮到你。本文还有配套的精品资源点击获取