### golang sqlite主从数据同步插件开发
思路
参考Mysql的主从同步机制,Mysql是产生binlog,然后把binlog日志同步到从服务上。
同理,我们按sql执行顺序记录所有的增删改查的sql语句,然后调用接口把sql语句传到从服务上执行。
数据库驱动使用的是 GORM。
编写gorm插件
golang
type Plugin interface {
Name() string
Initialize(*gorm.DB) error
}
type TracePlugin struct {
}
func (op *TracePlugin) Name() string {
return "tracePlugin"
}
func (op *TracePlugin) Initialize(db *gorm.DB) (err error) {
// 在这些sql操作后执行after方法,只记录增 删 改的语句
_ = db.Callback().Create().After("gorm:after_create").Register("after_create", after)
_ = db.Callback().Delete().After("gorm:after_delete").Register("after_delete", after)
_ = db.Callback().Update().After("gorm:after_update").Register("after_update", after)
return
}
func after(db *gorm.DB) {
err := db.Error
//sql执行成功
if err == nil {
//获取sql
sql := db.Dialector.Explain(db.Statement.SQL.String(), db.Statement.Vars...)
if strings.Contains(sql, "refresh_token") {
//过滤不需要的sql
return
}
//远程调用执行sql语句
sendExecSql(sql)
}
return
}
使用插件
golang
var SqliteDb *gorm.DB
func init() {
var err error
SqliteDb, err = gorm.Open(sqlite.Open("sqlite.db"), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 不要复数表名
},
Logger: logger.Default.LogMode(logger.Info), // 打印 SQL 语句
PrepareStmt: true,
})
if err != nil {
fmt.Printf("connect DB failed, err:%v\n", err)
return
}
fmt.Println("connect DB success")
db, err := SqliteDb.DB()
// 空闲状态下的最大连接数,默认的最大空闲连接数为2
db.SetMaxIdleConns(10)
// 最大打开连接数, 默认值为0(无限制)
db.SetMaxOpenConns(100)
// 设置连接可以重复使用的最长时间
db.SetConnMaxLifetime(time.Hour)
//使用插件
SqliteDb.Use(&plugins.TracePlugin{})
}
注意
sql要按顺序发送给从库执行,执行后要返回结果,返回成功后在发送下一条执行。
参考链接: