资讯动态

MySQL 4.1.18 老库救赎:解包、初始化到数据迁移实战指南

发布时间:2026/10/17 23:33:44 来源:尧图企业网站定制
简介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 位 ELFreadelf 会列出它启动时强制加载的共享库清单。常见的缺失项是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 --usermysql--basedir指定程序根目录--datadir指定数据文件落盘位置--usermysql会让初始化进程以 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 ) ENGINEMyISAM DEFAULT CHARSETlatin1; 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-setlatin1 \ --skip-lock-tables \ --quick \ --all-databases legacy_418.sql--skip-lock-tables绕开 FLUSH TABLES WITH READ LOCK避免在权限不足或长事务场景下卡死导出--quick让逐行读取而不是把整张表装进内存适用于大表的流式导出。导出文件里的 CREATE TABLE 语句默认带ENGINEMyISAM5.5 之后的库默认引擎是 InnoDB直接把文件导入新库不会保留 MyISAM提前要在导入端做好转换预期。导入新库前先检查导出文件里的引擎和字符集关键词grep -n ENGINE legacy_418.sql | head grep -n DEFAULT CHARSET legacy_418.sql | head若发现全部是 latin1 和 MyISAM而目标新库依赖 InnoDB 事务能力就要在导入前做一次批量替换。常见做法是sed -i s/ENGINEMyISAM/ENGINEInnoDB/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 rootlocalhost密码明明输入正确甚至 root 本来就是空密码也进不去。原因4.1 引入 41 字节的新密码哈希同时保留 16 字节的 old_password 兼容模式。如果服务端启用了 old-passwordsroot 账号的密码又存的是新格式认证环节就过不去。反过来也一样。解决用 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 PasswordPASSWORD() WHERE Userroot; FLUSH PRIVILEGES;密码清空后配合 old-passwords 开关就能让 16 位哈希协议接管认证。这个操作本质上是绕过权限表只建议在隔离环境里做。4.4 key_buffer 调太大32 位进程直接崩现象把 my.cnf 里的 key_buffer_size 调到 2G 后启动mysqld 进程立刻被 kill错误日志没有留下明显崩溃堆栈。原因i686 的 mysqld 是 32 位进程用户态地址空间上限约 3.5Gkey_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: Cant 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-datetime2005-01-01 00:00:00 \ --stop-datetime2005-03-01 00:00:00 binlog.000001 | \ /opt/mysql/bin/mysql -uroot legacy_data恢复前先确认 binlog 文件里没有破坏事务边界的记录否则整个事务会被跳过。零日期、超长字段、非法字符集这类数据在恢复链路上是最容易让导入中断的元凶。那次在模拟项目X里把 key_buffer 改崩之后我给自己定了个习惯拿到这种老包装第一件事是跑 file 和 ldd 确认架构与依赖第二件事是只给最小化配置启动参数一个一个加加一个验证一个。搬老库宁可慢也不能在启动阶段就消耗掉所有耐心。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑