Golang里数据库migration方案

Python中如果用SQLAlchemy的话,一般会用alembic来做migration。那么,Go呢?我一般用这个:

https://github.com/golang-migrate/migrate

官方的用法是生成migration文件(其实就是sql)时用命令行,升级时也可以用命令行。不过我更喜欢把升级文件和代码一起打包到二进制文件里。

我们依次来看。

创建migration文件

这个很简单,首先你要在自己电脑上装上 migrate 这个二进制:

curl -L https://github.com/golang-migrate/migrate/releases/download/$version/migrate.$platform-amd64.tar.gz | tar xvz

我是放到了 /usr/local/bin 下,其实也可以放到 $PATH 的任一自定义目录里。

生成migration文件,则执行以下命令即可:

$ migrate create -ext sql -dir ./migrations -seq create_user_table

执行之后,就会在 ./migrations 文件夹下,创建两个文件,都会包含 -seq 后的那一段,以 up.sqldown.sql 结尾。分别对应升级和降级操作该要执行的SQL。

migration操作,就写在对应的文件里。

升级

除了继续用 migrate 这个命令来进行升级降级操作,我们还可以把操作结合到程序里,我更喜欢这样做,好处如下:

  • 不用每个地方都打包 migrate 这个命令,或者安装这个二进制文件
  • 不用把migrations文件夹到处同步

咋做呢?这个时候就该祭出 go-bindata 这个包了,它的原理就是读文件,把文件的内容生成到一个 bindata.go 文件里,然后就可以通过内置的api,读取其中的内容。

那怎么结合到我们的应用里呢?直接上代码:

package main

import (
    "flag"
)

var migrateUp = flag.Bool("migrateUp", false, "run migration")

func main() {
    // ...
	if *migrateUp {
		s := bindata.Resource(migrations.AssetNames(),
			func(name string) ([]byte, error) {
				return migrations.Asset(name)
			})

		d, err := bindata.WithInstance(s)
		if err != nil {
			logrus.Panicf("failed to get migrations: %s", err)
		}
		m, err := migrate.NewWithSourceInstance("go-bindata", d, config.MigrateDBURL)
		if err != nil {
			logrus.Panicf("failed to get migrations: %s", err)
		}
		err = m.Up()
		if err != nil {
			logrus.Panicf("failed to migrate: %s", err)
		}
		return
	}
    // ...
}

就是介样,我们就可以愉快的把migration也编译到应用里,然后继续愉快的一个二进制包到处丢了。

当然了,要想使用 go-bindata,也得安装:

$ go get -u github.com/go-bindata/go-bindata/...

然后我在Makefile里加上这么一个动作:

bindata:
	cd migrations && go-bindata -pkg migrations .

duang,大功告成。


微信公众号
关注公众号,获得及时更新

更多文章
  • 预防缓存击穿
  • Go 1.13的errors挺香
  • flutter开发体验汇报
  • 自己封装一个好用的Dart HTTP库
  • Flutter应用启动后检查更新
  • Grafana Gravatar头像显示bug修复
  • flutter中使用RESTful接口
  • Vim YouCompleteMe使用LSP(以dart为例)
  • flutter webview加载时显示进度
  • SQLAlchemy快速更新或插入对象
  • 修复Linux下curl等无法使用letsencrypt证书
  • 欣赏一下K&R两位大神的代码
  • MySQL的ON DUPLICATE KEY UPDATE语句
  • 使用microk8s快速搭建k8s
  • Python中优雅的处理文件路径