简介:MySQL 4.1.18 的 Linux 二进制发行包,适用于 i686 架构并基于 glibc23 环境,适合数据库初学者和小型项目,解决在 PC 上搭建经典 MySQL 服务的基础需求。包内共 1269 个文件,大小仅 24.48MB,包含 mysqld 服务端、mysqladmin、mysqldump 等运维工具,以及 cnf/cfg 配置、h 头文件、txt/readme 文档和 SQL 测试脚本,目录结构完整,便于查看早期版本的组织方式。已有 132 人学习,是了解 MySQL 4.x 产品形态的实用样本。通过学习可掌握 tar 包解压、安装初始化、root 密码设置、用户权限授予与回收、备份恢复等基础操作,也能借助自带测试套件理解数据库功能边界,为后续学习新版 MySQL 打下根基。
1. 十年老包 mysql-standard-4.1.18:为什么还有人要翻它出来
我在某公司的归档机器上翻出过一份mysql-standard-4.1.18-pc-linux-gnu-i686-glibc23.tar,文件名一眼就让人回到 2005 年前后——基于 glibc 2.3 编译、i686 32 位架构的 MySQL 4.1.18 官方二进制发布包。现在还找它的人,多半不是图新鲜,而是要救一个跑了十来年的老调度系统,或者把某个陈年库里只认 latin1 的历史数据搬到新环境。它不依赖编译环境,解压就能跑,但要在现代 Linux 上复现,第一步就不是解包,而是先搞清楚动态链接器缺了哪些 32 位库。适合的读者是那些要在老系统、模拟项目X、离线环境里做数据搬运的工程师。你不需要它当生产库,只需要它把数据原原本本交出来。
2. 解开老包:先确定运行路线,再谈初始化配置
2.1 包里到底装了什么
解包后目录结构并不复杂,但里面每一块都有用途,搞混了会多走弯路。标准二进制包把程序、库、脚本、示例配置全打散了:
mysql-standard-4.1.18-pc-linux-gnu-i686-glibc23/ ├── bin/ │ ├── mysql │ ├── mysqldump │ ├── mysqlcheck │ ├── myisamchk │ └── my_print_defaults ├── libexec/ │ └── mysqld ├── scripts/ │ └── mysql_install_db ├── share/ │ └── mysql/ ├── support-files/ │ ├── my-medium.cnf │ └── mysql.server ├── docs/ │ └── manual.html └── sql-bench/bin 目录是客户端工具集,libexec 下放着真正的服务端守护进程 mysqld。scripts/mysql_install_db 负责初始化系统表,support-files 里有现成的示例配置和启停脚本。这里要注意一个 4.1 的老规矩:服务端不在 bin,在 libexec,写脚本时别把路径指错。
2.2 复现路径怎么选:容器、老发行版虚拟机、硬跑
在动手之前,先给这个 i686 包里两个最关键的二进制做一次体检:
file libexec/mysqld bin/mysql readelf -d libexec/mysqld | grep NEEDEDfile 会告诉你它是 32 位 ELF,readelf 会列出它启动时强制加载的共享库清单。常见的缺失项是libstdc++.so.6、libncurses.so.5和ld-linux.so.2。ld-linux.so.2是 32 位进程的动态链接器,现代 64 位系统默认不带,这正是硬跑时最容易看到的翻车点。
我一般会优先走容器路线:拉一个 i686 的容器镜像,把老踏包放进容器里跑。32 位运行库在容器里补齐,不污染宿主机,环境还能反复重建。其次是装一个 glibc 2.3 时代的老发行版虚拟机,这是最接近当年生产环境的做法,缺点是镜像难找、内核和文件系统兼容性都要额外操心。硬跑放最后,除非你能确认宿主机有完整的 32 位兼容库,否则第一阶段就会被 ld-linux 卡死,不划算。
2.3 初始化数据目录并调整 my.cnf
环境通了以后,初始化数据目录用的是 scripts/mysql_install_db,它和 MySQL 5.7 之后的--initialize是两个时代的产物。4.1 的脚本会直接创建 mysql 系统库和默认表,还会在终端打印一段 “Everything OK” 之类的输出。常见做法是先建一个专用系统用户,再执行:
groupadd mysql useradd -g mysql -s /sbin/nologin mysql mkdir -p /opt/mysql/data chown -R mysql:mysql /opt/mysql cd /opt/mysql ./scripts/mysql_install_db --basedir=/opt/mysql --datadir=/opt/mysql/data --user=mysql--basedir指定程序根目录,--datadir指定数据文件落盘位置,--user=mysql会让初始化进程以 mysql 身份创建系统表文件。这里有个经验:4.1 的初始化脚本对主机名解析非常敏感,一旦系统无法把当前主机名反向解析到 127.0.0.1,会直接报Neither host 'xxx' nor 'localhost' could be looked up,这一步失败后面全是白费力气。
初始化完成后,在 /opt/mysql 下建一个 my.cnf,配置尽量收敛:
[mysqld] basedir = /opt/mysql datadir = /opt/mysql/data port = 3306 socket = /tmp/mysql_418.sock skip-networking old-passwordsold-passwords是 4.1 时期连接老客户端的专用开关。当年很多应用用的是 16 位密码哈希,不开这个开关,老客户端或老版本驱动连上来就被密码协议挡住。skip-networking表示只走本地 socket,不监听 TCP 端口,做数据搬运时能少一层安全隐患。
2.4 首启与验证服务状态
配置写好后,用 libexec 下的 mysqld_safe 包装脚本启动更稳妥,它会自动帮你重定向错误日志:
/opt/mysql/bin/mysqld_safe --defaults-file=/opt/mysql/my.cnf & sleep 5 /opt/mysql/bin/mysqladmin --socket=/tmp/mysql_418.sock ping如果返回mysqld is alive,说明服务已经正常监听。这个包默认的 root 密码是空的,首启验证时直接用mysql -uroot登录即可。数据目录里的 err 日志是排错入口,遇到启动失败别急着改参数,先看一眼日志尾部,绝大多数原因写得很直白。
3. 数据操作与迁移:把 4.1 老库倒进现代库
3.1 建库建表与字符集:4.1 的规则和 5.x 不一样
4.1 的字符集体系是分层的:服务器层有character_set_server,连接层有character_set_client和character_set_results,表结构上还有 DEFAULT CHARSET。最坑的一点是 4.1 的 utf8 是简化版,不支持四字节字符,今天的 utf8mb4 在它眼里就是乱码。做数据归档时,我一般先确认这批数据的真实编码,再去建库。如果历史数据是 latin1,就别急着转 utf8,分两步走比一步到位可靠:
CREATE DATABASE legacy_data DEFAULT CHARACTER SET latin1; USE legacy_data; CREATE TABLE old_customers ( id INT PRIMARY KEY, name VARCHAR(80), remark TEXT ) ENGINE=MyISAM DEFAULT CHARSET=latin1; SHOW VARIABLES LIKE 'character_set%';连接层的字符集在导入前必须显式指定。4.1 默认的 client 字符集会随系统变量走,如果配置不对,latin1 数据被当成别的编码读进来,INSERT 阶段就开始悄悄损坏:
SET NAMES latin1; SET SESSION character_set_results = latin1;SET NAMES latin1同时改 client 和 results 两个变量,保证客户端发送的字节被服务器按 latin1 解释。char 字段的长度在 latin1 下按字节算,varchar 也一样,所以中文字符串长度要提前按字节数核对,别拿 5.x 时代按字符计算的思维套它。
3.2 mysqldump 导出与导入的兼容边界
旧版本导出的 SQL 在大部分情况下可以被新库直接消费,但反过来基本走不通。4.1 的 mysqldump 不认识新版的utf8mb4_0900_ai_ci,也不认识DEFAULT CURRENT_TIMESTAMP这类语法。导出时两个参数特别重要:
/opt/mysql/bin/mysqldump -uroot \ --default-character-set=latin1 \ --skip-lock-tables \ --quick \ --all-databases > legacy_418.sql--skip-lock-tables绕开 FLUSH TABLES WITH READ LOCK,避免在权限不足或长事务场景下卡死导出;--quick让逐行读取而不是把整张表装进内存,适用于大表的流式导出。导出文件里的 CREATE TABLE 语句默认带ENGINE=MyISAM,5.5 之后的库默认引擎是 InnoDB,直接把文件导入新库不会保留 MyISAM,提前要在导入端做好转换预期。
导入新库前,先检查导出文件里的引擎和字符集关键词:
grep -n 'ENGINE=' legacy_418.sql | head grep -n 'DEFAULT CHARSET' legacy_418.sql | head若发现全部是 latin1 和 MyISAM,而目标新库依赖 InnoDB 事务能力,就要在导入前做一次批量替换。常见做法是:
sed -i 's/ENGINE=MyISAM/ENGINE=InnoDB/g' legacy_418.sql mysql -uroot -p < legacy_418.sqlsql 文件里的表结构注释块/*!40101 SET ... */是 4.1 写的版本条件注释,新库导入时会按自己的版本号决定是否执行,不必手工清理。
3.3 导入后核对数据的常用方法
迁移之后,逐表比对行数是最低成本的验证手段。4.1 的 mysqldump 导出文件不会像新版那样自动带行数注释,所以只能在导出端提前记录基线:
for t in old_customers orders order_items; do echo "$t: $(/opt/mysql/bin/mysql -uroot -N -e "SELECT COUNT(*) FROM legacy_data.$t")" done导入到新库后,同一套循环再跑一遍,对比输出。除了行数,还要抽查字段极值。比如时间字段,4.1 允许0000-00-00这种零日期,而新版 MySQL 在严格模式下直接拒绝导入,导致中途报错。遇到这种情况,导出前先把零日期替换成 NULL 或有效日期,比在导入端反复调整 sql_mode 更省心。
4. 常见问题排查:老包启动失败与数据损坏的五个根源
4.1 动态链接器缺失:No such file or directory 与 libstdc 报错
现象:解包后在宿主机直接执行libexec/mysqld --version,提示No such file or directory,或者报libstdc++.so.6: cannot open shared object file。
原因:前者是系统里根本没有 32 位动态链接器 ld-linux.so.2,后者是 32 位 C++ 运行库缺失。file 显示 ELF 32-bit,但 64 位系统默认不安装多架构库,链接阶段直接失败。
解决:优先换容器或老发行版虚拟机,不要在宿主机上装一堆 32 位库去迁就一个十年前的程序。如果一定要硬跑,先确认系统的 32 位支持是否完整,把 i686 运行库装齐后再用 ldd 复查,ldd 输出里不再出现not found才继续。
4.2 mysql_install_db 报主机名解析失败
现象:执行初始化脚本时,终端输出Neither host 'web01' nor 'localhost' could be looked up with your resolve configuration。
原因:4.1 初始化阶段要向 mysql.user 系统表写入本机授权记录,需要通过解析器回查主机名。现代容器里 /etc/hosts 常常只写了 localhost,没有把容器 hostname 映射到 127.0.0.1。
解决:编辑 /etc/hosts,加上一行127.0.0.1 web01,让 hostname 能被反向解析。改完重新跑初始化脚本即可,这个行为在 4.1 里是硬校验,没有绕过参数。
4.3 老客户端连接被拒:密码协议不匹配
现象:应用连库时报Access denied for user 'root'@'localhost',密码明明输入正确,甚至 root 本来就是空密码,也进不去。
原因:4.1 引入 41 字节的新密码哈希,同时保留 16 字节的 old_password 兼容模式。如果服务端启用了 old-passwords,root 账号的密码又存的是新格式,认证环节就过不去。反过来也一样。
解决:用 skip-grant-tables 模式启动,登录后重新设置一次密码:
/opt/mysql/bin/mysqld_safe --defaults-file=/opt/mysql/my.cnf --skip-grant-tables & /opt/mysql/bin/mysql -uroot --socket=/tmp/mysql_418.sockUPDATE mysql.user SET Password=PASSWORD('') WHERE User='root'; FLUSH PRIVILEGES;密码清空后配合 old-passwords 开关就能让 16 位哈希协议接管认证。这个操作本质上是绕过权限表,只建议在隔离环境里做。
4.4 key_buffer 调太大,32 位进程直接崩
现象:把 my.cnf 里的 key_buffer_size 调到 2G 后启动,mysqld 进程立刻被 kill,错误日志没有留下明显崩溃堆栈。
原因:i686 的 mysqld 是 32 位进程,用户态地址空间上限约 3.5G,key_buffer 在 4.1 里走 malloc 分配,2G 加上其他缓冲区直接触及进程地址空间天花板。这个问题在 5.x 之后就很少见了,因为 64 位下地址空间不再是瓶颈。
解决:4.1 的老库不值得给大内存。key_buffer 控制在 256M 以内,sort_buffer 保持默认,innodb_buffer_pool_size 在 32 位下也谨慎设置。数据搬运场景追求的是稳定,不是吞吐。
4.5 mysqldump 导出卡死:锁表权限与长事务
现象:mysqldump 执行到中途停止,终端长时间无输出,或者报Got error: 1017: Can't find file这类读写异常。
原因:4.1 的 mysqldump 默认执行 FLUSH TABLES WITH READ LOCK 来保证一致性导出。当 mysql 用户缺少 RELOAD 权限,或目标表正在被长时间写入锁占用时,导出就会卡在锁等待。有时候是磁盘写满,错误被日志吞掉了,只看终端发现不了。
解决:导出前查权限,导出命令显式加--skip-lock-tables,同时确认数据目录所在分区剩余空间大于预估导出文件大小的两倍。对于 MyISAM 表,锁表风险小于 InnoDB,但 4.1 的 InnoDB 版本很老,一旦崩溃恢复,卡死概率明显高于 MyISAM。
5. 验证老库完整性:CHECK TABLE、myisamchk 与 binlog 的边界
数据迁移完成后,验证要分两层做。第一层是在线检查,用 mysqlcheck 走一遍标准校验:
/opt/mysql/bin/mysqlcheck -uroot --socket=/tmp/mysql_418.sock \ --check --check-only-upgrade legacy_datamysqlcheck 会转发为 CHECK TABLE 语句,能查出索引损坏、行数不一致、页校验失败等问题。4.1 的 MyISAM 表在线检查出问题后,不能指望它自动修复,需要停掉服务后走离线工具:
/opt/mysql/bin/myisamchk -c /opt/mysql/data/legacy_data/old_customers.MYI /opt/mysql/bin/myisamchk -r /opt/mysql/data/legacy_data/old_customers.MYI-c只做检查,-r是修复模式。myisamchk 操作期间必须保证 mysqld 没有占用表文件,否则两个进程同时写索引文件会造成二次损坏。修复完再用 mysqlcheck 复查一遍。
第二层是 binlog 层面的边界确认。4.1 的 binlog 格式是早期版本,新版 mysqlbinlog 工具解析它经常直接拒绝,或者要求额外指定--base64-output。我在模拟项目X里试着用新版 tools 去解析 4.1 的 binlog,失败后只能转回老环境拿老版本工具导出,再手工拼接 SQL。所以 old_password 协议只是一个开始,binlog 格式的兼容性是另一个更隐蔽的边界。4.1 的 binlog 恢复只建议在同一环境中完成,跨版本恢复前先验证解析工具是否认这个文件,再做基于位置的恢复:
/opt/mysql/bin/mysqlbinlog --start-datetime="2005-01-01 00:00:00" \ --stop-datetime="2005-03-01 00:00:00" binlog.000001 | \ /opt/mysql/bin/mysql -uroot legacy_data恢复前先确认 binlog 文件里没有破坏事务边界的记录,否则整个事务会被跳过。零日期、超长字段、非法字符集这类数据,在恢复链路上是最容易让导入中断的元凶。
那次在模拟项目X里把 key_buffer 改崩之后,我给自己定了个习惯:拿到这种老包装,第一件事是跑 file 和 ldd 确认架构与依赖,第二件事是只给最小化配置启动,参数一个一个加,加一个验证一个。搬老库,宁可慢,也不能在启动阶段就消耗掉所有耐心。希望帮到你。
本文还有配套的精品资源,点击获取