Migrate Microsoft SQL Server to MySQL Database
最近完成了一个小项目的数据库迁移,从微软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的官方教程:
Install Docker Engine on Debian
https://docs.docker.com/engine/install/debian/
2)运行SQL Server 2019 Docker镜像的官方教程:
Quickstart: Run SQL Server container images with Docker
https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver15&pivots=cs1-bash
3)SQL Server 2019的微软官方Docker镜像:
dockerhub - Microsoft SQL Server
https://hub.docker.com/_/microsoft-mssql-server
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 - Using the MySQL Workbench Migration Wizard
https://dev.mysql.com/doc/workbench/en/wb-migration-wizard.html
但是我所安装的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的设置说明如下:
MySQL innodb_autoinc_lock_mode 详解
https://www.cnblogs.com/JiangLe/p/6362770.html