
简介面向郑州大学计算机与人工智能学院《数据库系统原理》课程学习者的一份实验报告文档适合正在完成数据库管理系统认识、万里数据库GreatSQL部署与实验报告撰写任务的学生参考。压缩包内仅含1个docx文件大小约3.69MB排版完整便于直接查阅或打印。已有509人学习。文档围绕实验一展开包含实验目的、实验内容、实验类型与学时分配等栏目涵盖万里数据库GreatSQL的安装、启动与停止虚拟机中CentOS7环境配置关闭SELinux和防火墙的原因与命令依赖包安装及二进制包解压步骤并梳理基本表、视图、触发器、存储过程等逻辑组件与物理存储方式。报告还给出截图编号、图题、表格格式、问题更正和结果分析等写作规范可帮助读者理解实验流程、复现关键操作、整理排错思路并对照完善自己的实验报告。1. 一台上机课留下的环境数据库实验报告为什么值得单独装一遍那份《数据库系统原理》实验报告看着简单真正让人卡住的从来不是 SQL 本身而是实验一的环境准备。虚拟机上 CentOS 7、GreatSQL 8.0.32-25 二进制包、关闭 SELinux 与防火墙、配 systemd 服务这几步只要错一个字符后面八个实验全都要停摆。我见过最典型的一次翻车把setenforce 0敲成了setenforce0命令不报错SELinux 照旧是 Enforcing数据库初始化时数据目录被拦日志里只有一行 Permission denied排查了两个小时。这类实验环境对版本和路径的敏感度远高于普通业务部署值得按安装文的标准走一遍。2. 版本对齐CentOS 7 上选 GreatSQL 8.0.32-25 的 glibc 与依赖账实验环境最容易忽略的不是数据库本身而是操作系统底下的 glibc 和依赖包。GreatSQL 官方给 8.0.32-25 这个版本准备了多个二进制包命名里带glibc2.17的那份是给 CentOS 7 用的因为 CentOS 7 自带的 glibc 版本就是 2.17。选错包解压后mysqld --version直接报GLIBC_2.28 not found这类错误不会告诉你该换哪个包只会让你以为是系统坏了。2.1 为什么选 minimal 二进制包而不是源码编译实验环境的核心诉求是「可复现」不是「极致性能」。源码编译一套 GreatSQL 8.0 在单核虚拟机上要跑四十分钟以上中途缺一个cmake版本或者 gcc 版本不对整个编译就得重来。二进制 minimal 包已经把服务端、客户端、初始化工具打好了解压即用路径固定出了问题也好对照。常见做法是包类型适用场景本实验是否选用minimal 二进制包快速搭环境、教学实验、单机验证选用full 二进制包需要 debug 符号、额外组件不选体积大且无必要源码编译要改参数、改存储引擎、做二次开发不选实验不涉及minimal意味着包里只保留运行必需的可执行文件像mysqld、mysql、mysqladmin、mysqldump都在但不带测试套件和多余插件。对做完九个实验来说够用缺点是排错时少了些辅助工具需要自己补net-tools这类基础命令。2.2 虚拟机规格与系统层的最小准备实验报告里写的运行环境是 VMwaer CentOS 7 或以上这个「或以上」在实际操作里要打个折扣。CentOS 8 之后默认的firewalld行为和nftables后端跟 7 不一样systemctl stop firewalld之后端口策略可能还残留实验一里那些ss -lntp验证步骤就会对不上。我一般建议老老实实用 CentOS 7.9内存给 2GB 以上磁盘 20GB 起步因为 GreatSQL 的 InnoDB 默认就要吃掉一部分内存和磁盘。系统装完先确认两件事主机名和 IP 固定。虚拟机用 NAT 模式时 IP 每次重启可能变实验报告里要截图ss -lntp的输出IP 一变截图就对不上重装一遍最省事的反而是把BOOTPROTO设成static。# 查看系统版本和内核确认是 CentOS 7.x cat /etc/centos-release uname -r # 查看 glibc 版本决定下载哪个二进制包 ldd --version | head -n 1 # 确认磁盘剩余空间GreatSQL 初始化后 datadir 会占几百兆 df -h /usr/local /var/libldd --version输出的第一行就是 glibc 版本2.17 对应glibc2.17那个包2.28 及以上才考虑glibc2.28的包。df -h要重点看/var/lib所在分区因为datadir默认就放在/var/lib/mysql分区满了会在初始化阶段直接失败而不是启动阶段。2.3 依赖包一次性装齐的分类清单实验报告里那条yum install命令很长一次性贴进去容易看花眼也不方便判断哪个包装失败了。按用途拆成四类更好记编译与头文件pkg-config、openssl-devel、libaio-devel、numactl-devel、jemalloc-devel运行时库libaio、numactl-libs、openssl、jemallocPerl 相关perl、perl-Data-Dumper、perl-Digest-MD5、perl-JSON、perl-Test-Simple基础工具与脚本依赖net-tools、python2# 一次性安装-y 表示自动确认避免交互卡住 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 # 装完检查关键包是否都在 rpm -qa | grep -E libaio|numactl|jemalloc|openssllibaio是 InnoDB 异步 IO 的依赖缺了它mysqld启动时会退回同步 IO性能差但不报错很容易被忽略。jemalloc是 GreatSQL 推荐的内存分配器在my.cnf里通过malloc-lib指定后才生效。python2看着多余其实是为了兼容 CentOS 7 上一些老版本的mysql-test脚本和监控工具实验用不到但装上不影响。提示如果yum源被改过导致安装失败先执行yum clean all yum makecache再重试不要急着换源。3. 装前开关SELinux 关闭、firewalld 停用与用户目录权限这三件事在实验报告里是「运行环境配置」一节写得很短但每一条都直接决定数据库能不能起来。SELinux 决定进程能不能碰数据目录firewalld 决定 3306 端口能不能被连上用户和目录决定文件属主对不对。顺序上要先关开关再建目录最后才解压安装倒过来做很容易出现「目录建在 SELinux 拦截之前」的混乱。3.1 关 SELinux 的两种状态与一条容易写错的命令SELinux 有三个状态Enforcing、Permissive、Disabled。实验要的是彻底Disabled因为Permissive只是不拦截、照样记日志重启后如果配置没改回来又回到Enforcing。这里有个血泪经验命令行写的是setenforce 0中间是空格不是等号。写成setenforce0时 shell 会把它当成一条叫setenforce0的命令直接报command not found如果脚本里没检查返回值就会带着 Enforcing 状态继续往下装。# 临时生效立即从 Enforcing 切换到 Permissive setenforce 0 # 永久生效把配置文件里的 SELINUX 整行替换成 disabled sed -i /^SELINUX/c\SELINUXdisabled /etc/selinux/config # 验证临时状态和永久配置都要看 getenforce grep ^SELINUX /etc/selinux/configsed里那个/c\表示替换整行注意斜杠后面要跟反斜杠再跟新内容这是 GNU sed 的标准写法。原文里的sed -i /^SELINUX/cSELINUXdisabled /etc/selinux/config少了一个空格和反斜杠在部分环境下会把文件名当成替换内容改完之后config文件内容会错乱。改完必须用grep复核getenforce显示的是运行态重启前和重启后要分别看一次。关闭 SELinux 的理由实验报告里列了三条避免限制数据库的特权操作、简化配置、减少访问控制检查带来的性能开销。前两条是实打实的第三条在实验规模下影响很小不必当真。真正要记住的是SELinux 开着时mysqld对/var/lib/mysql的写操作会被 label 策略拦log-error里只留一行笼统的权限拒绝很容易误判成文件权限问题。3.2 firewalld 停用与 3306 端口防火墙的处理比 SELinux 简单但也要分清「停止当前服务」和「禁止开机自启」两个动作。只做stop下次重启 firewalld 又回来了实验做到一半端口不通那种感觉相当难受。# 禁止开机自启避免重启后防火墙又起来 systemctl disable firewalld # 立即停止当前运行的防火墙 systemctl stop firewalld # 查看状态确认是 inactive (dead) systemctl status firewalld # 确认 3306 端口在监听数据库启动后再执行 ss -lntp | grep mysqldsystemctl status firewalld输出里的Active:一行是判断依据inactive (dead)才算停干净。ss -lntp里的-l是监听态、-n是数字端口、-t是 TCP、-p是显示进程名四个参数组合起来正好回答「谁在监听哪个端口」。实验里在虚拟机内部做开发和测试关防火墙是最省事的做法。生产环境当然不能这么干正确做法是firewall-cmd --add-port3306/tcp --permanent开端口这一条在实验报告里没写但面试和实际运维里一定会被问到值得顺手记下来。3.3 mysql 用户、数据目录与属主GreatSQL 不允许用 root 跑mysqld这是 8.0 系列的硬性要求。所以要建一个专用的mysql用户而且这个用户不能登录系统家目录指向/dev/nullshell 设成/sbin/nologin。这套参数看着别扭其实是在做最小权限万一数据库进程被利用也没法通过这个账号拿到交互式 shell。# 创建 mysql 组和用户-d /dev/null 不分配家目录-s /sbin/nologin 禁止登录 /sbin/groupadd mysql /sbin/useradd -g mysql mysql -d /dev/null -s /sbin/nologin # 创建数据目录 mkdir -p /var/lib/mysql # 把数据目录和安装目录的属主改成 mysql chown -R mysql:mysql /var/lib/mysql chown -R mysql:mysql /usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal # 验证属主 ls -ld /var/lib/mysql id mysqlid mysql的输出里uid和gid应该都在groups里只有mysql。如果chown漏了安装目录后续mysqld --initialize会去写basedir下的临时文件写不进去就报Cant create/write to file这个报错信息不会直接指向属主问题得靠ls -l反查。注意/var/log那个chown在原文里也出现了把整个/var/log改成 mysql 属主是有风险的会影响其他服务的日志写入。更稳的做法是只针对/var/log/mysql这类专用目录改或者在my.cnf里把log-error指到/var/lib/mysql下面。4. 落盘安装解压 GreatSQL、写 my.cnf、挂 systemd 服务前面都是准备工作这一章才是真正让 GreatSQL 在系统里「有个位置」的过程。顺序是解压到/usr/local、写my.cnf、写 systemd 单元文件、初始化数据目录、启动服务。每一步都有一两个参数值得停下来想一下因为实验报告要求「对所作的选择进行思考为何要进行这样的配置」这些思考点直接对应实验一的评分项。4.1 解压路径与软链接二进制包统一放/usr/local这是 Linux 下第三方软件的惯例位置好处是跟系统自带的/usr/bin分开不会污染系统路径。解压出来是个带完整版本号的长目录名命令行里敲起来很痛苦所以几乎所有人都会建一个软链接。cd /usr/local # 下载 minimal 二进制包-O 指定保存文件名便于识别 wget https://product.greatdb.com/GreatSQL-8.0.32-25/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal.tar.xz # 解压xz 格式用 tar xf 会自动识别压缩算法 tar xf GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal.tar.xz # 建立软链接后面所有配置都指向 /usr/local/greatsql ln -s /usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal /usr/local/greatsql # 验证解压结果和版本 ls /usr/local/greatsql/bin | head -n 10 /usr/local/greatsql/bin/mysqld --versionmysqld --version正常输出类似mysqld Ver 8.0.32-25 for Linux on x86_64这一行就同时验证了 glibc 匹配、二进制完整、可执行权限三件事。如果这里报GLIBC_2.28 not found说明包选错了换glibc2.28版本重来如果报Permission denied说明属主没改对回第 3 章处理。软链接的好处不只是少敲字后面my.cnf里的basedir、systemd 文件里的ExecStart、环境变量PATH都可以统一写/usr/local/greatsql将来升级到 8.0.33 只需要改软链接指向配置文件一行不动。4.2 /etc/my.cnf 里真正要改的几行my.cnf是 GreatSQL 的全局配置位置在/etc/my.cnf。实验报告里只写了「编辑 GreatSQL 全局配置文件」没给内容这里补一份能跑通的最小配置[mysqld] # 安装根目录指向软链接方便后续升级 basedir /usr/local/greatsql # 数据目录必须提前创建并改好属主 datadir /var/lib/mysql # socket 文件位置本地免密登录靠它 socket /var/lib/mysql/mysql.sock # 监听端口实验用默认 3306 port 3306 # 错误日志排错第一现场 log-error /var/lib/mysql/greatsql-error.log # pid 文件systemd 停服务时要用 pid-file /var/lib/mysql/greatsql.pid # 字符集避免中文姓名乱码实验数据里有中文 character-set-server utf8mb4 collation-server utf8mb4_general_ci # 兼容老客户端实验中可能用到旧版 mysql 命令行 default_authentication_plugin mysql_native_password # 内存分配器配合前面装的 jemalloc malloc-lib /usr/lib64/libjemalloc.so.1 [client] socket /var/lib/mysql/mysql.sock default-character-set utf8mb4逐条说几个容易踩的character-set-server utf8mb4是必须的。实验三往Students表里插了「张华」「李玉」这些中文姓名如果字符集留默认的latin1插进去再查出来就是问号实验报告里的截图会很难看而且这种乱码是写入时就错了事后改字符集也救不回来。default_authentication_plugin mysql_native_password是为了兼容。GreatSQL 8.0 默认用caching_sha2_password老版本的客户端库连不上会报Authentication plugin caching_sha2_password cannot be loaded。实验环境里用的客户端不一定是最新的改成mysql_native_password最省事。生产环境不建议这么改安全性会降一档。malloc-lib指向jemalloc的.so文件路径因系统而异CentOS 7 上通常是/usr/lib64/libjemalloc.so.1用rpm -ql jemalloc可以确认实际路径。这一行写错不会导致启动失败但会静默退回 glibc 的 malloc性能优化就白做了。innodb_buffer_pool_size在实验环境里可以不写默认值 128M 够用。如果虚拟机内存给到 4GB 以上设成1G能明显加快建表和查询速度但要注意别超过物理内存的 60%。4.3 greatsql.service 单元文件systemd 单元文件决定了能不能用systemctl start greatsql这种标准方式管理服务。文件放/lib/systemd/system/greatsql.service内容大致如下[Unit] DescriptionGreatSQL Server 8.0.32-25 Afternetwork.target [Service] # 用专用用户运行禁止 root Usermysql Groupmysql # 启动命令--defaults-file 要放在最前面 ExecStart/usr/local/greatsql/bin/mysqld --defaults-file/etc/my.cnf # 停止时用 mysqladmin 优雅关闭 ExecStop/usr/local/greatsql/bin/mysqladmin --defaults-file/etc/my.cnf shutdown # 异常退出后自动拉起 Restarton-failure RestartSec10 # 资源限制避免文件句柄不够 LimitNOFILE65535 [Install] WantedBymulti-user.targetExecStart里--defaults-file的位置很关键必须紧跟可执行文件放在其他参数后面会被忽略。这是mysqld的老规矩位置错了它照样启动但读的是默认路径的配置datadir一类的设置全部不生效。LimitNOFILE65535是给 InnoDB 开文件句柄用的。默认的 1024 在多表场景下不够会报Too many open files这个错误在实验阶段不容易碰到但在导入大批量表数据时会突然出现。写完单元文件要执行systemctl daemon-reload让 systemd 重新扫描。这一步漏了的话systemctl start greatsql会报Unit greatsql.service not found看起来像是文件没写对其实只是没重载。4.4 初始化数据目录与首次启动到这一步datadir还是空的直接systemctl start会失败必须先初始化。GreatSQL 8.0 用--initialize生成系统表用--initialize-insecure生成一个空密码的 root实验环境用后者更省事省得去日志里翻临时密码。# 初始化数据目录--user 指定运行用户--basedir 和 --datadir 显式指定 /usr/local/greatsql/bin/mysqld --initialize-insecure \ --usermysql \ --basedir/usr/local/greatsql \ --datadir/var/lib/mysql # 重载 systemd 并启动服务 systemctl daemon-reload systemctl start greatsql # 检查服务状态 systemctl status greatsql初始化成功的标志是/var/lib/mysql下出现ibdata1、mysql、sys、performance_schema这些目录和文件greatsql-error.log里最后一行是ready for connections。如果日志里出现Aborting基本是属主或 SELinux 的问题回第 3 章复查。systemctl status greatsql显示active (running)还不够紧接着要确认mysqld进程真的在# 查进程应该能看到 mysqld 和一个 --defaults-file 参数 ps -ef | grep mysqld # 查端口应该能看到 3306 处于 LISTEN ss -lntp | grep mysqld # 查数据文件确认初始化产物都在 ls /var/lib/mysql这三条命令正好对应实验报告里图 2、图 3、图 4 的位置。ps -ef | grep mysqld的输出里除了mysqld本身还会有一条grep mysqld那是 grep 进程自己别误判成两个实例。ss -lntp里要看到0.0.0.0:3306或*:3306如果只看到127.0.0.1:3306说明bind-address被限制了远程工具连不上。首次登录用mysql -uroot -S /var/lib/mysql/mysql.sock-S指定 socket 路径比走 TCP 更稳。登进去之后立刻改密码ALTER USER rootlocalhost IDENTIFIED BY 新密码;然后FLUSH PRIVILEGES;。实验报告里没写这一步但空密码的 root 留在环境里后面用可视化工具连的时候会各种别扭。5. 避坑清单GreatSQL 8.0.32 装完起不来的五种现场装数据库这件事成功的路径只有一条失败的姿势各有各的不同。下面五条是我在实验环境和测试机上反复遇到的按「现象 → 原因 → 解决」记遇到问题先对照这里比翻日志快。5.1 服务启动即退出日志只有一行 Aborting现象systemctl start greatsql返回成功但systemctl status显示failedgreatsql-error.log最后一行是[ERROR] Aborting前面没有任何具体原因。原因九成是datadir属主不对或者目录非空。mysqld初始化时要求datadir要么完全为空要么已经是合法初始化过的目录。如果之前初始化失败过一次目录里留了半截文件第二次初始化会直接退出。解决先ls -la /var/lib/mysql确认目录内容。如果是半截初始化产物rm -rf /var/lib/mysql/*清空后重新chown -R mysql:mysql /var/lib/mysql再跑一次--initialize-insecure。清空之前确认没有别的库实验环境可以放心删生产环境绝对不行。5.2 客户端报 Cant connect to local MySQL server through socket现象mysql -uroot报错提示 socket 路径找不到但ss -lntp明明显示 3306 在监听。原因客户端默认去/var/lib/mysql/mysql.sock或/tmp/mysql.sock找 socket而my.cnf里socket配的是另一个路径两边对不上。CentOS 上还常见一种情况/tmp被 systemd 的PrivateTmp隔离服务看到的/tmp和用户看到的不是同一个。解决统一 socket 路径在[mysqld]和[client]两段都写socket /var/lib/mysql/mysql.sock。连接时显式带-S /var/lib/mysql/mysql.sock。如果还是不行用mysql -h127.0.0.1 -P3306 -uroot -p走 TCP绕开 socket 直接验证服务是否正常。5.3 中文数据插进去变成问号现象INSERT语句执行成功SELECT出来中文全是???SHOW VARIABLES LIKE character%显示一堆latin1。原因建库或建表时没指定字符集继承了服务端的默认值而服务端my.cnf里没配character-set-server。这种错误是写入时就发生的不是显示问题。解决my.cnf里补character-set-server utf8mb4和collation-server utf8mb4_general_ci重启服务。已经乱码的数据救不回来只能删表重建。建库时显式写CREATE DATABASE DB DEFAULT CHARACTER SET utf8mb4;建表时也带上DEFAULT CHARSETutf8mb4双保险。5.4 systemctl 提示 Unit greatsql.service not found现象单元文件明明写了systemctl start greatsql却报服务不存在。原因三种可能。文件没放在/lib/systemd/system/或/etc/systemd/system/下文件名和systemctl里写的名字不匹配比如文件叫greatsql.service命令敲成greatSQL写完没执行systemctl daemon-reload。解决ls /lib/systemd/system/ | grep great确认文件名然后systemctl daemon-reload重载再systemctl list-unit-files | grep great看是否被识别。文件名大小写敏感一律用小写。5.5 初始化时报 Cant create/write to file现象mysqld --initialize-insecure跑到一半报Cant create/write to file /usr/local/greatsql/xxx路径指向安装目录而不是数据目录。原因basedir下的目录属主还是 rootmysql用户没有写权限。初始化过程要往basedir下写临时文件权限不够就中断。解决chown -R mysql:mysql /usr/local/GreatSQL-8.0.32-25-Linux-glibc2.17-x86_64-minimal注意要改真实目录改软链接本身不生效软链接的属主和目标的属主是两回事。改完用sudo -u mysql touch /usr/local/greatsql/test验证一下mysql用户能写能写再重跑初始化。注意这五条里有一半是「权限」问题另一半是「路径」问题。装 GreatSQL 遇到报错先看路径对不对、属主对不对再看参数比直接搜错误信息高效得多。6. 验证跑通从进程端口到逻辑组件的九项自检装完不算完实验报告的第一章明确要求「了解数据库系统的逻辑组件」基本表、视图、触发器、存储过程、约束这几样要在系统里能查出来。所以最后一章的验证不能只停在systemctl status得从进程层一路查到逻辑层正好把实验一的验收点全部覆盖。我一般按下面这张表走一遍从上到下前一项不过就不看后一项序号检查项命令通过标准1服务状态systemctl status greatsqlactive (running)2进程ps -ef | grep mysqld有且只有一个 mysqld3端口ss -lntp | grep mysqld3306 处于 LISTEN4数据文件ls /var/lib/mysql有 ibdata1、mysql、sys5登录mysql -uroot -S /var/lib/mysql/mysql.sock进入 mysql 提示符6版本SELECT VERSION();8.0.32-257字符集SHOW VARIABLES LIKE character%;均为 utf8mb48逻辑组件查information_schema四张表能查出结果集9建表验证建库建表插一行中文中文不乱码前四项是系统层验证第 5 项之后进到数据库内部。第 8 项对应实验一的逻辑组件部分四条命令分别查视图、触发器、存储过程、约束-- 查视图系统库里的视图也算能返回结果说明元数据可读 SELECT TABLE_NAME FROM information_schema.VIEWS LIMIT 5; -- 查触发器 SELECT TRIGGER_NAME, EVENT_MANIPULATION FROM information_schema.TRIGGERS; -- 查存储过程ROUTINE_TYPE 过滤掉函数 SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_TYPEPROCEDURE; -- 查约束KEY_COLUMN_USAGE 里能看到主键和外键 SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA DB;这四张表都是information_schema里的系统视图空库状态下视图和触发器可能查不到数据返回Empty set也是正常的只要不报错就说明元数据服务在工作。约束查询要看TABLE_SCHEMA不指定库名会返回系统库的一堆记录看不出实验表的情况。第 9 项是端到端验证直接拿实验二的建表语句跑一遍-- 建库并指定字符集 CREATE DATABASE DB DEFAULT CHARACTER SET utf8mb4; USE DB; -- 建一张带主键和约束的表 CREATE TABLE STUDENTS( Sno char(9) PRIMARY KEY, Sname char(10) NOT NULL, Sex char(2), Birthday DATE, Speciality char(20), Dno char(4) ); -- 插一行中文数据 INSERT INTO STUDENTS VALUES(201705001,张华,男,1999-12-16,计算机,CS); -- 查回来中文不乱码就算通过 SELECT * FROM STUDENTS;这条链路走通说明字符集、存储引擎、主键约束、数据目录写入全都正常实验二到实验九的建表、查询、索引操作就有了可靠底座。如果第 9 项中文乱码回 5.3 处理如果建表报Table STUDENTS already exists说明之前建过DROP TABLE再重来。有一个细节值得单独说SELECT * FROM STUDENTS;的输出如果中文正常但宽度对不齐那是客户端字符集的问题用mysql --default-character-setutf8mb4 -uroot -S ...重新登录即可跟服务端没关系。实验报告要截图建议在登录时就带上这个参数省得截完图发现排版乱了重来。从那以后我每次装完一套数据库环境都会把这张九项表从头到尾走一遍哪怕前面已经systemctl status看到 running 了也不省。因为 running 只说明进程活着不说明数据目录能写、字符集对、逻辑组件可读而这三件事恰恰是后面八个实验能不能顺利做下去的前提。装环境最贵的成本不是装的那半小时是装完之后带着错误配置一路做实验、最后推倒重来的那几个小时。希望帮到你。本文还有配套的精品资源点击获取