|
上篇《数据迁移丨借助 AI 从 PostgreSQL 到 GreatSQL》介绍了如何使用 AI + pg_dump/COPY 的方式将 PostgreSQL 迁移到 GreatSQL 中,各位同学看过之后,会发现两款数据库还是有一些差异,例如对象层次结构、数据类型等方面,如果采用人工来迁移,还是会比较麻烦,所以本篇将介绍,如何使用开源工具 pg2mysql 工具从 PostgreSQL 到 GreatSQL。
pg2mysql 工具是一款开源工具,由 VMware 公司提供,主要用于将数据从 PostgreSQL 迁移至 MySQL 或 GreatSQL。其核心价值在于数据兼容性检查与迁移功能。在实际迁移操作之前,该工具会仔细检查 MySQL/GreatSQL 的表结构与 PostgreSQL 中相应表结构是否兼容。若检测到诸如字段长度不足之类的潜在问题,它会向用户发出提示,以便用户进行修正。
pg2mysql 工具主要是用 Go 语言编写的,遵循 Apache - 2.0 许可证。不过需要注意的是,目前这个项目已经归档,不再进行定期更新了。但对于有能力的朋友而言,可以基于该项目进行进一步的开发:)
以上链接可以直接下载 pg2mysql 最新 v0.0.6 版本,授权后可直接运行:
$ chomd 755 pg2mysql_linux
$ ./pg2mysql_linux -h
2024/10/28 14:52:40 error: Usage:
pg2mysql_linux [OPTIONS] <migrate | validate | verify>
Application Options:
-c, --config= Path to config file
Help Options:
-h, --help Show this help message
Available commands:
migrate Migrate data from PostgreSQL to MySQL
validate Validate that the data in PostgreSQL can be migrated to MySQL
verify Verify migrated data matches
源码安装方式需要有 GO 语言环境:
$ go version
go version go1.22.5 linux/amd64
版本没有强要求,go1.22.5 版本可以正常编译运行。
新建一个文件夹,用于存放 pg2mysql 工具源码:
$ mkdir /usr/local/pg2mysql
$ cd /usr/local/pg2mysql
拉取 pg2mysql 工具源码:
$ git clone https://github.com/pivotal-cf/pg2mysql.git
$ cd pg2mysql/
如果采用手册中的方法go get github.com/pivotal-cf/pg2mysql/cmd/pg2mysql会报错:go: go.mod file not found in current directory or any parent directory. 'go get' is no longer supported outside a module. To build and install a command, use 'go install' with a version, like 'go install example.com/cmd@latest' For more information, see https://golang.org/doc/go-get-install-deprecation or run 'go help get' or 'go help install'.是因为目前新版本 Go 语言在模块(module)相关的使用方式上有了变化,直接先拉取源码在操作。
进入 pg2mysql 源码文件夹后,可以看到以下文件:
$ ls
LICENSE config.go migrator_test.go postgres.go vendor
Makefile db.go mysql.go postgresrunner verifier.go
README.md go.mod mysqlrunner testdata verifier_test.go
cmd go.sum pg2mysql_suite_test.go validator.go watcher.go
commands migrator.go pg2mysqlfakes validator_test.go
接下来构建项目:
$ go mod init pg2mysql
$ go mod tidy
构建完成后,可以编译该工具:
$ go build -o pg2mysql cmd/pg2mysql/main.go
在文件夹下就会发现 main
可执行文件,接着授权即可运行:
# 授权
$ chmod 755 pg2mysql
# 授权完成即可运行
$ ./pg2mysql -h
2024/10/30 13:58:20 error: Usage:
pg2mysql [OPTIONS] <migrate | validate | verify>
Application Options:
-c, --config= Path to config file
Help Options:
-h, --help Show this help message
Available commands:
migrate Migrate data from PostgreSQL to MySQL
validate Validate that the data in PostgreSQL can be migrated to MySQL
verify Verify migrated data matches
这里有 error 没关系,看源码可知 log.Fatalf("error: %s", err) 会带有一个error,并不是无法使用。
首先需要创建配置,创建 PostgreSQL 和 MySQL/GreatSQL 的链接信息:
$ cat > config.yml <<EOF
mysql:
database: some-dbname
username: some-user
password: some-password
host: 192.168.10.1
port: 3306
postgresql:
database: some-dbname
username: some-user
password: some-password
host: 192.168.10.2
port: 5432
ssl_mode: disable
EOF
例如,想迁移 PostgreSQL 数据库 pg_to_greatsql 库下的 users 表到 GreatSQL 数据库:
mysql:
database: pg_to_greatsql
username: root
# GreatSQL 密码设置的是空
password:
host: 192.168.6.88
port: 3306
postgresql:
database: pg_to_greatsql
username: postgres
password: GreatSQL@666
host: 192.168.6.52
port: 5432
ssl_mode: disable
这里有两个问题:
ssl_mode 参数可以看:
设置为 disable
指的是 I don't care about security, and I don't want to pay the overhead of encryption. 意思就是不关心安全性也不加密。
GreatSQL 和 PostgreSQL 都有远程链接限制需要打开。GreatSQL 打开方式可以阅读:
pg2mysql 工具不支持协助建库建表,所以需要自行建库建表。可以参考上篇,利用 AI 协助建表:
搜索关键词 表结构迁移 即可跳转对应内容。
建库建表完成后,使用参数 validate
验证:
$ pg2mysql -c config.yml validate
users OK
如果没有问题的话,会显示 OK。如果有问题的话会显示以下内容:
$ pg2mysql -c config.yml validate
found incompatible rows in apps with IDs [2]
found incompatible rows in app_usage_events with IDs [9 10 11 12]
found incompatible rows in events with IDs [16 17 18]
如果存在任何不兼容的行(如上所述),则需要在继续迁移之前对其进行修改。
验证完成以后,就可以使用 migrate
迁移数据了:
$ pg2mysql -c config.yml migrate --truncate
Disabling constraints...OK
Truncating users...OK
Migrating users...OK
inserted 1010000 rows
Enabling constraints...OK
!!!注意!!!--truncate 命令会清空目标表,作用是保证数据一致,如果目标表有数据,请不要使用该参数。
阅读源码可知,迁移的方式也是采用 INSERT INTO
的 SQL 语句:
// pg2mysql 中 migrator.go 的源码
preparedStmt, err := m.dst.DB().Prepare(fmt.Sprintf(
"INSERT INTO %s (%s) VALUES (%s)",
table.Name,
strings.Join(columnNamesForInsert, ","),
strings.Join(placeholders, ","),
))
if err != nil {
return fmt.Errorf("failed creating prepared statement: %s", err)
}
如果大数据迁移,肯定会很慢,可以考虑关闭双1等方法提高插入速度。
迁移后运行验证程序以确认数据已按预期迁移:
$ pg2mysql -c config.yml verify
Verifying table users...
OK
验证对 PostgreSQL 中每个表的每一行的内容进行精确比较,以查看 GreatSQL 中是否存在匹配的行。
根据源码,该工具会遍历源数据库中的所有表,遍历源数据库中的每一行,然后在判断行是否存在于目标数据库中:
// 例如下面的代码,准备检查目标数据库中是否存在行的语句
stmt = fmt.Sprintf(`SELECT EXISTS (SELECT 1 FROM %s WHERE %s)`, table.Name, strings.Join(colVals, " AND "))
preparedStmt, err := dst.DB().Prepare(stmt)
if err != nil {
return fmt.Errorf("failed to prepare statement: %s", err)
}
这就导致了会使得该操作异常的慢。
pg2mysql 工具虽然可以简化迁移的流程,但是速度和效率来说有点太慢了,当然速度和源端/目标端的机器配置决定的,但是方法是采用大数量级的 INSERT INTO
还是会对数据库产生不小的负载。所以我推荐可以试着采用下面的方法:
pg2mysql -c config.yml validate
选项验证是否兼容pg2mysql -c config.yml verify
选项验证是否按预期迁移当然,有能力的同学也可以将该工具优化下:)
合作电话:010-64087828
社区邮箱:greatsql@greatdb.com