ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MySQL 8.0免安装部署:Windows与Linux配置初始化与服务注册

MySQL 8.0免安装部署:Windows与Linux配置初始化与服务注册

简介:面向需要快速搭建本地 MySQL 8.0 环境的开发者、运维学习者与教学演示场景,这份免安装压缩包提供解压即用的数据库运行目录,省去安装器与系统服务配置环节。包内共420个文件,整体约186.28MB,主要包含exe与dll构成的服务端程序和依赖库,sdi、sql及ibd、ibdata1、undo、ib_logfile等元数据与InnoDB数据日志文件,pem证书、my.ini与cnf配置、bat启动批处理,以及readme、ChangeLog等说明文档,目录结构贴近官方发行版,便于排查与二次调整。已有594人学习下载,说明其在本地数据库快速部署场景中具有一定参考价值。默认端口3306、root密码root,解压到D盘可直接运行;若需更换存放位置,可通过my.ini中的basedir和datadir完成迁移,适合本地开发、课程实验和临时测试使用。

1. 免安装不等于省心:MySQL 8.0 压缩包的第一道版本门槛

拿到 mysql8.0免安装 压缩包的人,第一反应往往是解压后双击bin里的mysqld.exe,结果窗口一闪而过;在 Linux 上直接执行bin/mysqld,也可能只留下一行报错。mysql 免安装版没有安装向导、没有默认my.ini、没有注册服务,也没有现成的 root 密码,初始化参数错一个,后面全是黑匣子。更隐蔽的是版本差异:mysql8 默认认证插件是caching_sha2_password,老客户端会报 2059;lower_case_table_names在初始化后不能再改,Windows 和 Linux 默认值还不一样。这套环境适合需要多版本并存、不能跑 installer、想把 mysql数据库 放在独立目录里的开发者。下面按 Windows 和 Linux 两条线,把解压、配置、初始化、注册服务、验证和救火一次走完。

2. 装前把环境钉死:MySQL 8.0 免安装包的版本、依赖与目录预检

免安装包看起来只是“解压”,实际仍然依赖运行库、目录权限、端口和服务名。先把这些外部条件钉死,后面初始化失败的概率会低很多。我一般会先确认三件事:包型对不对、路径能不能写、3306 有没有被旧服务占着。这三件事任何一件出问题,mysqld都只会给你一个很短的报错,甚至只在错误日志里留一行。

2.1 Windows zip 与 Linux tar.xz 的包型差异

Windows 下常见的是mysql-8.0.xx-winx64.zip,解压后直接用,不跑.msi。下载时不要选带debug或test的包,那些是给排查和测试用的,体积大、启动参数也不一样。zip 包依赖 Visual C++ 运行库,尤其是vcruntime140_1.dll这类文件,机器上缺了就会在启动时提示“找不到 xxx.dll”。常见做法是装一次 Microsoft Visual C++ 2015-2022 x64 运行库,再解压 mysql 包,不要等报错了才回头补。

Linux 下常见的是mysql-8.0.xx-linux-glibc2.28-x86_64.tar.xz这类二进制包,包名里的glibc版本要和系统对得上。系统ldd --version低于包要求的版本时,mysqld会直接报GLIBC_2.xx not found。另外要装libaio,CentOS 系一般是libaio,Debian/Ubuntu 系一般是libaio1;缺少时mysqld启动会提示libaio.so.1: cannot open shared object file。

平台常见包名主要依赖服务方式
Windowsmysql-8.0.xx-winx64.zipVC++ 运行库、空数据目录mysqld --install注册 Windows 服务
Linuxmysql-8.0.xx-linux-glibc2.28-x86_64.tar.xzglibc、libaio、目录权限systemd 托管或mysqld_safe

版本选择上,8.0 系列的小补丁尽量统一,不要一台机器 8.0.2x、另一台 8.0.3x,然后拿同一个数据目录来回拷。8.0 的数据字典升级是单向的,低版本打不开高版本的数据目录,跨大版本更不能直接挂 5.7 的data。如果只是本地开发,选一个稳定的 8.0 补丁版即可;如果要做多版本并存,目录名里带上版本号,例如/usr/local/mysql80和/usr/local/mysql57,不要共用一个basedir。

2.2 运行库、路径与端口的三项预检

Windows 上先看运行库和端口。mysqld --version如果直接弹缺少 DLL,就先补 VC++ 运行库;如果版本能打印出来,说明二进制本身能启动。端口用netstat查,不要只看任务管理器里有没有mysqld,旧服务可能换了进程名还在占 3306。服务名也要查,MySQL80被占用时再注册会提示服务已存在,后面启动的可能是旧服务。

REM 查 3306 是否被占用,最后一列是 PID netstat -ano | findstr :3306 REM 查是否已经存在同名 mysql 服务 sc query MySQL80 REM 看当前 mysqld 能否正常打印版本,缺 DLL 会在这里暴露 D:\mysql80\bin\mysqld --version

netstat输出里LISTENING对应的 PID 可以再到任务管理器里核对,确认是旧 MySQL 还是其他程序。sc query只查服务名,不查端口;如果服务存在但没启动,也要先决定是复用还是删掉重装。mysqld --version是最便宜的预检,能跑通再往下走。

Linux 上先看动态库和端口。ldd输出里出现not found就不要急着初始化,先把缺的库补上。端口用ss -lntp查,比netstat快。数据目录所在分区要留足空间,innodb的 redo、binlog、临时表都往数据目录和tmpdir里写,空间不够时初始化可能只报一个很模糊的“Operating system error”。

# 检查 mysqld 的动态库依赖,出现 not found 先补库 ldd /usr/local/mysql/bin/mysqld | grep "not found" # 查 3306 监听,顺便看 PID 和进程名 ss -lntp | grep 3306 # 看数据目录所在分区剩余空间 df -h /data

ldd只检查直接依赖,libaio这种运行时才加载的库不一定能全部暴露,所以还要结合启动日志看。ss的-l是监听状态,-n不做域名解析,-p带进程信息。df -h看的是挂载点剩余空间,不要等初始化到一半才去清理。

路径预检经常被忽略。Windows 下不要放在C:\Program Files\mysql,空格和权限都会让my.ini里的路径变复杂;用D:\mysql80这种短路径。Linux 下不要放在/tmp或用户家目录,数据目录用/data/mysql80/data,日志和 socket 分开放。路径里出现中文、空格、括号时,my.ini和命令行参数都容易解析错,常见做法是统一用英文短路径。

2.3 解压与目录规划

Windows 解压时先建目标目录,再把 zip 内容解进去。注意 zip 里有时会多一层mysql-8.0.xx-winx64,解压后要确认bin直接在D:\mysql80\bin,而不是D:\mysql80\mysql-8.0.xx-winx64\bin。多一层时后面所有basedir都要改,不如一开始就摆正。data目录先建空目录,log目录也先建,my.ini里的log-error指向不存在的目录时,Windows 服务启动会直接失败。

REM 建短路径,避免空格和中文 mkdir D:\mysql80 REM 解压 zip 到目标目录,按实际包名替换 tar -xf mysql-8.0.xx-winx64.zip -C D:\mysql80 REM 建空数据目录和日志目录,初始化前 data 必须为空 mkdir D:\mysql80\data mkdir D:\mysql80\log REM 确认 bin 在根目录下 dir D:\mysql80\bin\mysqld.exe

tar -xf在 Windows 10 及以上自带,能解 zip;如果包内多一层目录,解压后把里层内容移到D:\mysql80。data目录只建空目录,不要手工放文件。dir是最后确认,路径不对时后面注册服务会报basedir找不到。

Linux 解压要建专用账户和软链。不要用 root 跑mysqld,初始化时用--user=mysql,数据目录属主给mysql。软链的好处是升级时只换链接,basedir不用改。数据、日志、临时目录、文件导入目录分开,权限只给mysql,不要chmod 777。

# 建 mysql 专用账户,禁止登录 shell groupadd mysql useradd -r -g mysql -s /bin/false mysql # 解压到 /usr/local,按实际包名替换 tar -xvf mysql-8.0.xx-linux-glibc2.28-x86_64.tar.xz -C /usr/local # 做软链,后续升级只换软链 ln -s /usr/local/mysql-8.0.xx-linux-glibc2.28-x86_64 /usr/local/mysql # 数据、日志、临时目录、导入目录分开 mkdir -p /data/mysql80/{data,log,tmp,upload} chown -R mysql:mysql /data/mysql80 chmod 750 /data/mysql80/data

useradd -r建系统账户,-s /bin/false禁止登录。ln -s的软链名是/usr/local/mysql,后面basedir都指它。mkdir -p一次建多层,{data,log,tmp,upload}是 shell 展开。chown只给数据根目录,chmod 750让同组可读可执行、其他用户无权限。upload是给secure_file_priv用的,后面配置文件里会指到它。

目录规划可以按下面这张表对照,不要把所有东西都塞进data:

目录用途建议权限
D:\mysql80或/usr/local/mysql程序目录basedirroot 可读可执行,mysql 可读
D:\mysql80\data或/data/mysql80/data数据目录datadir仅 mysql 可读写
D:\mysql80\log或/data/mysql80/log错误日志、慢日志、binlogmysql 可写
/data/mysql80/tmp临时表空间tmpdirmysql 可写
/data/mysql80/uploadsecure_file_priv导入导出mysql 可写

注意:lower_case_table_names必须在初始化前定好。Windows 默认是 1,Linux 默认是 0,初始化完成后再改会启动失败。跨平台迁移时先确认这个值,不要等表名大小写出问题才回头改。

3. Windows 解压即用:my.ini、初始化与服务注册一条线

Windows 下的免安装版最容易卡在“服务能注册但启动不了”。原因通常不是 mysql 本身,而是my.ini路径写错、data目录非空、日志目录不存在、VC++ 运行库缺失。我的顺序是:先手写my.ini,再前台初始化,初始化成功后再注册服务。不要一上来就mysqld --install,服务启动失败时错误会被吞到事件查看器里,排查成本高。

3.1 手写 my.ini:字符集、端口、数据目录

my.ini放在D:\mysql80\my.ini,不要放在bin里。路径统一用正斜杠,Windows 下D:/mysql80/data比D:\mysql80\data少一层转义麻烦。字符集用utf8mb4,排序规则用utf8mb4_0900_ai_ci,这是 8.0 的默认组合,不要沿用 5.7 的utf8mb4_general_ci。

[mysqld] ; 端口和安装目录 port=3306 basedir=D:/mysql80 datadir=D:/mysql80/data ; 字符集与排序规则 character-set-server=utf8mb4 collation-server=utf8mb4_0900_ai_ci ; 表名大小写:Windows 默认 1,初始化后不能改 lower_case_table_names=1 ; 认证插件:老客户端多时再考虑改成 mysql_native_password default_authentication_plugin=caching_sha2_password ; 连接数与超时 max_connections=200 wait_timeout=28800 interactive_timeout=28800 ; 错误日志、慢日志 log-error=D:/mysql80/log/mysql-error.log slow_query_log=1 slow_query_log_file=D:/mysql80/log/mysql-slow.log long_query_time=2 ; 文件导入导出目录,必须先建好 secure_file_priv=D:/mysql80/upload ; 时区与 SQL 模式 default-time-zone='+08:00' sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION [client] port=3306 default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4

basedir和datadir必须写绝对路径,且datadir初始化前为空。lower_case_table_names=1是 Windows 默认行为,如果后面要迁到 Linux,最好一开始就统一成 0 或 1,不要两边混用。default_authentication_plugin写caching_sha2_password是 8.0 默认,老客户端连不上时不要急着全局降级,先按第 5 章的用户级改法处理。log-error和slow_query_log_file的目录要先存在,否则服务启动时直接报错。secure_file_priv指向的目录也要先建,不然LOAD DATA和导出会失败。sql_mode保留了严格模式,不要为了省事直接清空,清空后脏数据写入很难回头查。

3.2 初始化数据目录的两种方式

初始化有两个常用参数:--initialize生成随机 root 密码并写进错误日志,--initialize-insecure生成空密码 root。前者适合正式环境,后者只适合本机第一次登录、马上改密。初始化时加--console把日志打到控制台,失败能直接看到。--defaults-file要放在命令行前面,路径必须是绝对路径。

REM 进入 bin 目录 cd /d D:\mysql80\bin REM 方式一:生成随机密码,初始化后到错误日志里找 temporary password mysqld --defaults-file=D:\mysql80\my.ini --initialize --console REM 方式二:空密码 root,仅限本机首次,登录后立刻改密 mysqld --defaults-file=D:\mysql80\my.ini --initialize-insecure --console

--defaults-file告诉 mysqld 读哪个配置文件,不写时会按默认路径找,容易读到别的实例配置。--initialize会创建系统表空间、数据字典和 root 用户,完成后data目录不再是空目录。--console把错误输出到当前窗口,初始化失败时先看这里,再去看D:/mysql80/log/mysql-error.log。如果提示data directory has files,说明datadir非空,先确认没有旧数据再清空,不要直接删整个目录。

初始化完成后,data目录下会出现mysql、sys、performance_schema等目录,mysql-error.log里能看到temporary password或root@localhost is created with an empty password。如果是--initialize,把临时密码复制出来,登录后第一件事就是改密;如果是--initialize-insecure,登录时直接回车,然后执行ALTER USER。

3.3 注册服务与首次登录改密

初始化成功后再注册服务。--install后面跟服务名,--defaults-file仍然要带绝对路径。服务名不要和旧服务重名,重名时先sc query确认,必要时用mysqld --remove 旧服务名删掉旧服务。启动用net start,停止用net stop,不要直接杀进程。

REM 注册服务,服务名 MySQL80,配置文件必须绝对路径 mysqld --install MySQL80 --defaults-file=D:\mysql80\my.ini REM 启动服务 net start MySQL80 REM 查服务状态 sc query MySQL80 REM 如果服务名冲突,先卸载旧服务再注册 REM mysqld --remove MySQL80

--install只是写注册表,不会自动初始化数据目录;顺序必须是先初始化、再注册。net start启动失败时,先看D:/mysql80/log/mysql-error.log,再看 Windows 事件查看器里的应用程序日志。sc query的STATE是RUNNING才算启动成功,STOP_PENDING或PAUSED都不正常。--remove只删服务,不删数据目录,删之前确认服务名对应的是哪个实例。

首次登录用mysql -uroot -p -h127.0.0.1 -P3306。用-h127.0.0.1而不是只写localhost,可以避开命名管道和 socket 的差异。空密码直接回车,临时密码就粘贴。登录后先看当前用户和认证插件,再改密:

-- 查看当前用户和认证插件 SELECT user, host, plugin FROM mysql.user WHERE user = 'root'; -- 修改 root 本地密码,密码按实际复杂度替换 ALTER USER 'root'@'localhost' IDENTIFIED BY 'Replace_With_Strong_Pass_2024'; -- 刷新权限 FLUSH PRIVILEGES; -- 确认密码策略是否启用,启用时弱密码会直接报错 SHOW VARIABLES LIKE 'validate_password%';

mysql.user在 8.0 里仍然是视图/表,plugin列能看到caching_sha2_password还是mysql_native_password。ALTER USER改的是root@localhost,不要改成root@%,远程 root 不是好习惯。FLUSH PRIVILEGES在ALTER USER后不是必须,但改完权限表后执行一次更稳。validate_password如果启用,密码要带大小写、数字和符号,否则会报ER_NOT_VALID_PASSWORD。

3.4 环境变量与客户端验证

把D:\mysql80\bin加进系统PATH,后面在任意目录都能执行mysql、mysqldump、mysqladmin。加完要新开一个命令行窗口,旧窗口不会自动刷新环境变量。验证分三层:版本、连通性、实际查询。

REM 新开 cmd 后验证版本 mysql --version REM 用 mysqladmin 探活,能返回 mysqld is alive 说明服务在 mysqladmin -uroot -p -h127.0.0.1 -P3306 ping REM 登录后执行一条查询,确认字符集和端口 mysql -uroot -p -h127.0.0.1 -P3306 -e "SELECT VERSION(), @@port, @@character_set_server;"

mysql --version只证明客户端能跑,不证明服务通。mysqladmin ping会真正连一次服务,返回mysqld is alive才算通。-e后面直接跟 SQL,适合脚本化检查;输出里能看到版本、端口和字符集。如果提示'mysql' 不是内部或外部命令,说明PATH没生效或路径写错,回到环境变量里确认D:\mysql80\bin没有多余引号。

4. Linux tar.xz 部署:mysql 用户、权限与 systemd 托管

Linux 下免安装部署的重点不是解压,而是权限和托管。用 root 跑mysqld能起来,但后面文件属主全乱,备份和升级都难受。我的做法是:专用mysql用户、数据目录独立、my.cnf放/etc/my.cnf、systemd 托管。这样重启、开机自启、日志收集都有统一入口。

4.1 建用户组与解压到 /usr/local

账户和目录在第 2 章已经建过,这里补依赖和权限细节。mysqld需要libaio,CentOS 系用yum install -y libaio,Debian/Ubuntu 系用apt install -y libaio1。如果ldd还提示libnuma.so.1,再补numactl-libs。不要用--nodeps强行跳过,缺库时启动会直接退出。

# 补运行时依赖,按系统包管理器替换 yum install -y libaio # 确认 mysql 用户和目录属主 id mysql ls -ld /usr/local/mysql /data/mysql80 /data/mysql80/data # 给程序目录读权限,数据目录只给 mysql 读写 chown -R root:root /usr/local/mysql chown -R mysql:mysql /data/mysql80 chmod 750 /data/mysql80/data

id mysql确认用户存在,ls -ld看目录属主和权限。程序目录归 root 更安全,mysql只需要读和执行;数据目录归mysql,因为mysqld以mysql身份写文件。chmod 750让同组可进入,其他用户无权限。不要chmod -R 777 /data,这会让任何本地用户都能读数据文件。

4.2 my.cnf 参数取舍

Linux 的配置文件放/etc/my.cnf,不要放在bin里。user=mysql让mysqld启动后降权;socket、pid-file、log-error都放到/data/mysql80下,避免和系统自带的 mysql 冲突。lower_case_table_names=0是 Linux 默认,如果从 Windows 迁过来,要提前决定是否改成 1,但只能在初始化前改。

[mysqld] user=mysql basedir=/usr/local/mysql datadir=/data/mysql80/data socket=/data/mysql80/mysql.sock port=3306 pid-file=/data/mysql80/mysql.pid log-error=/data/mysql80/log/mysql-error.log character-set-server=utf8mb4 collation-server=utf8mb4_0900_ai_ci lower_case_table_names=0 default-time-zone='+08:00' max_connections=500 innodb_buffer_pool_size=1G log_bin=/data/mysql80/log/mysql-bin binlog_expire_logs_seconds=604800 slow_query_log=1 slow_query_log_file=/data/mysql80/log/mysql-slow.log long_query_time=2 secure_file_priv=/data/mysql80/upload bind-address=0.0.0.0 [client] socket=/data/mysql80/mysql.sock default-character-set=utf8mb4

innodb_buffer_pool_size=1G是示例,按机器内存调,常见做法是给物理内存的 50% 到 70%,但不要超过可用内存,否则系统会开始换页。log_bin开启 binlog,binlog_expire_logs_seconds=604800是 7 天自动清理,8.0 用秒数参数,不要再用 5.7 的expire_logs_days。bind-address=0.0.0.0表示监听所有网卡,内网机器可以改成具体内网 IP,减少暴露面。secure_file_priv指向的目录必须存在且属主是mysql,否则导入导出会报错。socket路径要和客户端[client]里一致,否则本地登录会去找/var/lib/mysql/mysql.sock。

4.3 初始化与 systemd 托管

初始化用--initialize生成临时密码,不要用--initialize-insecure上生产。--user=mysql让初始化出来的文件属主正确。初始化完成后,临时密码在log-error里,用grep找。如果data目录非空,先确认没有旧数据再清空,不要直接覆盖。

# 初始化数据目录,临时密码会写到错误日志 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --initialize --user=mysql # 从错误日志里取临时密码 grep 'temporary password' /data/mysql80/log/mysql-error.log # 看目录属主,确认是 mysql ls -ld /data/mysql80/data

--defaults-file让初始化读/etc/my.cnf,--initialize会创建系统表空间和数据字典,--user=mysql让文件归mysql。grep出来的临时密码只显示一次,复制后尽快登录改密。ls -ld如果看到属主是 root,说明初始化时没带--user=mysql或目录权限不对,后面启动会写不进去。

systemd 单元放/etc/systemd/system/mysqld.service。Type=notify让 systemd 等 mysqld 真正就绪;ExecStart带--defaults-file;ExecStop用kill -TERM走正常关闭;LimitNOFILE调大文件描述符;Restart=on-failure让异常退出后自动拉起。

[Unit] Description=MySQL Server 8.0 After=network.target [Service] User=mysql Group=mysql Type=notify ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf ExecStop=/bin/kill -TERM $MAINPID LimitNOFILE=65535 Restart=on-failure RestartPreventExitStatus=1 [Install] WantedBy=multi-user.target

User和Group让服务以mysql身份运行,不要用 root。Type=notify需要 mysqld 支持 systemd 通知,8.0 二进制包一般支持;如果启动一直卡在activating,可以临时改成Type=simple排查。ExecStop用TERM信号让 mysqld 做正常 shutdown,不要用kill -9。RestartPreventExitStatus=1避免配置错误时无限重启。改完单元文件要systemctl daemon-reload。

# 重载 unit 并设置开机自启 systemctl daemon-reload systemctl enable --now mysqld # 看状态和最近日志 systemctl status mysqld journalctl -u mysqld -n 100 --no-pager

enable --now同时做开机自启和立即启动。status看Active: active (running)才算成功;失败时看journalctl的最后 100 行,常见是my.cnf路径、权限、端口占用。--no-pager防止日志被分页器截住,适合复制报错。

4.4 首次连接与远程账号

首次登录用 socket 或127.0.0.1。用-S /data/mysql80/mysql.sock走本地 socket,避免 TCP 和权限问题。临时密码登录后立刻改密,然后创建应用账号。不要用root@'%'给远程,应用账号按库授权,能限制来源 IP 就限制。

# 用 socket 登录,输入错误日志里的临时密码 mysql -uroot -p -S /data/mysql80/mysql.sock
-- 修改 root 本地密码 ALTER USER 'root'@'localhost' IDENTIFIED BY 'Replace_With_Strong_Pass_2024'; -- 创建应用账号,来源限制到内网网段 CREATE USER 'app_user'@'10.%' IDENTIFIED BY 'Replace_App_Pass_2024'; -- 只给业务库的增删改查权限 GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'10.%'; FLUSH PRIVILEGES; -- 确认账号和认证插件 SELECT user, host, plugin FROM mysql.user WHERE user IN ('root', 'app_user');

ALTER USER改的是root@localhost,本地 socket 登录匹配这个 host。CREATE USER的'10.%'是来源网段,按实际内网改

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进