最近完成了一个小项目的数据库迁移,从微软SQL Server 2016迁移到MySQL 8。过程没什么复杂,只是需要注意一下数据类型和SQL语法的转换。
1 环境
原数据库是SQL Server 2016。迁移的目标环境,操作系统为Debian 11,安装了MySQL 8。
2 还原SQL Server数据库备份
拿到手的是SQL Server数据库备份,需要还原出来再迁移。幸好微软推出了SQL Server的Linux版,而且官方提供了可用于开发测试的Docker镜像,几个步骤就部署并还原好SQL Server数据库。
参考资料:
1)在Debian上安装Docker的官方教程:
2)运行SQL Server 2019 Docker镜像的官方教程:
3)SQL Server 2019的微软官方Docker镜像:
3 MySQL的准备
由于SQL Server的数据库表名不区分大小写,MySQL为了兼容相关SQL语句,也需要设置表名不区分大小写。即设置MySQL的参数lower_case_table_names=1,MySQL在存储和查询时,都把表名转为小写后再执行处理。
这里最麻烦的是,如果MySQL原来设置了lower_case_table_names=0(一般Linux上安装MySQL的默认值),需要把data文件夹清空,更新设置后重新初始化MySQL的数据。如果直接更改该值,MySQL重启后会报错。
关键的操作步骤:
1)修改MySQL的配置文件(Debian的默认路径为:/etc/mysql/mysql.conf.d/mysql.cnf),在[mysqld]节点下,加入一行lower_case_table_names=1。
2)重新初始化MySQL(已有数据库的话,先做好备份,初始化后再还原),先清空数据文件夹(Debian的默认路径:/var/lib/mysql),然后执行以下命令:
mysqld --user=root --initialize --lower-case-table-names=1
初始化成功后,root用户的密码会记录在/var/log/mysql/error.log。
4 迁移数据库定义
即导出原数据库表的create语句。一般推荐使用MySQL Workbench的Migration功能,官方文档如下:
但是我所安装的MySQL Workbench不能连接到Docker部署的SQL Server,所以使用了已安装的HeidiSQL,导出原数据库表的create table语句,然后手工修正为MySQL的语法。一些修改操作如下:
- 修正字符编码,特别是设置了COLLATE的,需求改为
COLLATE utf8mb4_0900_ai_ci。 - 修正默认值设置,例如
DEFAULT '(0)'改为DEFAULT '0',DEFAULT getDate()改为DEFAULT CURRENT_TIMESTAMP。 - 自增型字段会被忽略,需要加上
AUTO_INCREMENT。 - 字段类型转换,例如
NVARCHAR改为VARCHAR,BIT改为TININY(1),MONEY改为DECIMAL(19,4)。 - 需要补上索引设置。
5 迁移数据库的数据
即导出所有数据的insert语句,然后在目标数据库利用source命令进行导入。一般也是推荐使用MySQL Workbench操作,不用担心语法和数据类型的问题。
我使用了DBeaver导出所有表的insert语句,然后手工修正为MySQL语法。需要注意:
- 一般一条
insert语句包含10000行数据,已提高导入时的效率。 - 所有表名以
数据库名.dbo开头的,都改为以数据库名开头。 - 列名以中括号“[]”括住的,要改为“`”。
6 修改程序的SQL语句
主要是把SQL Server的语法,改为MySQL的语法。总结如下:
TOP改为LIMIT。getDate()改为CURRENT_TIMESTAMP。- 去掉表名前的
dbo.。 WITH(NOLOCK)的处理。SQL Server加了WITH(NOLOCK)的语句,如果MySQL的InnoDB设置innodb_autoinc_lock_mode=0,需要特殊处理该语句,否则直接去掉WITH(NOLOCK)。
关于InnoDB的设置说明如下: