Mysql迁移数据到SQLite以及go-sqlite3 requires cgo的坑博客的`Mysql`数据库切换成`
前言
去年双十一购买的一年期的新人优惠服务器(2C 4G)快到期了,这几天准备购买一个海外的服务器。但海外的服务器价格比较昂贵,也是第一次使用,所以想先买一个1C 1G
的。
现在的4G
的服务器内存占用率差不多是50%
多一点,其中占用比较大的是docker
中跑的Elastic Search
服务和Mysql
服务。
目前我的博客就正在使用其中的Mysql
服务,如果要把博客系统迁移到新的服务器上,同时也要把Mysql
迁移过去。
如果从4G
降低到1G
,内存可能就不够用了,所以就想着把博客的Mysql
数据库切换成SQLite
数据库,从而降低内存的使用。
从Mysql迁移数据到SQLite
把当前服务器中的Mysql
的数据库迁移SQLite
只需要两步:
- 使用
mysqldump
命令输出dump.sql
文件 - 使用
mysql2sqlite
shell工具来生成sqlite.db
为什么使用mysql2sqlite来迁移
尝试过在DataGrip
(Jetbrains家的数据库管理客户端)去Copy Data
,但关于一些日期的处理不好,所以我选择mysql2sqlite
。事实证明这个迁移脚本确实比较好用。
生成sql文件
在一台安装了mysql-client
(mysql的shell客户端)的机器上进行SQL
文件的输出,mysqldump
是默认安装在该库中的命令。
以我所在的MacOS
机器上为例,如果想要安装mysql-client
,最简单的方式就是使用brew install mysql-client
。
然后使用mysqldump
命令进行mysql
数据的文件导出:
mysqldump -u root -P 3306 -h your_mysql_ip_address -p --skip-extended-insert your_database > dump_mysql.sql
生成sqlite.db
在Unix
机器上,比如Linux和MacOS
下载「mysql2sqlite」,去执行下面的命令:
./mysql2sqlite dump_mysql.sql | sqlite3 sqlite3.db
然后就能得到sqlite
的数据库文件了。接下来就可以直接访问这个数据库了。
MacOS 和 Linux上的很多系统都自带
Sqlite3
,使用sqlite3
命令查看是否已有该数据库环境。
进行切换
代码修改
从这个「commit」开始进行代码的改造,其实改造起来非常简单,但中间还是遇到了一个小坑耽误了不少时间。
我在go
的后端工程中使用「XORM」来作为数据库的ORM
,它本身就支持Mysql
和SQLite3
数据库的支持,我只需要在底层把Mysql
的引擎切换成SQLite3
即可,其他的都不需要改变。
package infrastructure
import (
_ "github.com/mattn/go-sqlite3"
"log"
"time"
"tunan-blog/env"
"xorm.io/xorm"
"xorm.io/xorm/names"
)
var Sqlite *xorm.Engine
func init() {
println("sqlite3 connect db file", env.Prop.Sqlite3.File)
newEngine, err := xorm.NewEngine("sqlite3", env.Prop.Sqlite3.File)
if err != nil {
log.Println(err)
return
}
// 设置驼峰转换
newEngine.SetMapper(names.GonicMapper{})
// 时区
newEngine.TZLocation, _ = time.LoadLocation("Asia/Shanghai")
err = newEngine.Ping()
if err != nil {
log.Println(err)
return
}
Sqlite = newEngine
}
当我在本地完成编译调试完成,将GO
的可执行文件打包好,上传到服务器上执行时,就报错连接不上数据库了。
go-sqlite3 requires cgo的坑
一开始没有很好的打印出报错日志(大晚上的脑袋昏昏沉沉),导致我排查了很久:
- 文件路径
- 文件权限
- 文件是否损坏
这些问题都不存在,最后尝试去询问XORM
的开发者:
没有回复后,我就去洗澡去了,等洗完澡回来后发现我打印的ERR
有问题,当我把真正的ERR
:
Binary was compiled with 'CGO_ENABLED=0, go-sqlite3 requires cgo to work. This is a stub'
打印出来后,发现是需要将CGO_ENABLED=1
设置成这样来编译。
正如前文说的,我是在本地(MacOS)中使用
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o tunan-blog cmd/tunan-blog/main.go
来打包成Linux
上的可执行文件,然后上传到服务器上执行的。
当我设置CGO_ENABLED=1
去打包时,再次报错了:
implicit declaration of function 'setresgid' is invalid in C99
在上面的这个issue
中发现了解决方法,来自惊帆的BLOG的一篇文章: 使用go语言进行交叉编译的时候遇到的一些问题
通过上面文章中的解决方案:
MacOS
上安装musl-cross
brew install FiloSottile/musl-cross/musl-cross
- 修改打包命令为
apt-get -y install musl
- 执行可执行文件的
Linux
(我的是Ubuntu系统)上安装musl
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -o tunan-blog cmd/tunan-blog/main.go
然后重新运行即可。
结束
最后成功将底层的Mysql
切换成了SQLite3
,等新的服务器买了之后,只要把sqlite.db
文件Copy过来就可以了,比Mysql
轻量且方便!
转载自:https://juejin.cn/post/7418117491720781833