### golang sqlite主从数据同步插件开发
思路
参考Mysql的主从同步机制,Mysql是产生binlog,然后把binlog日志同步到从服务上。
同理,我们按sql执行顺序记录所有的增删改查的sql语句,然后调用接口把sql语句传到从服务上执行。
数据库驱动使用的是 GORM。
编写gorm插件
type Plugin interface {Name() stringInitialize(*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 {//获取sqlsql := db.Dialector.Explain(db.Statement.SQL.String(), db.Statement.Vars...)if strings.Contains(sql, "refresh_token") {//过滤不需要的sqlreturn}//远程调用执行sql语句sendExecSql(sql)}return
}
使用插件
var SqliteDb *gorm.DBfunc init() {var err errorSqliteDb, 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()// 空闲状态下的最大连接数,默认的最大空闲连接数为2db.SetMaxIdleConns(10)// 最大打开连接数, 默认值为0(无限制)db.SetMaxOpenConns(100)// 设置连接可以重复使用的最长时间db.SetConnMaxLifetime(time.Hour)//使用插件SqliteDb.Use(&plugins.TracePlugin{})
}
注意
sql要按顺序发送给从库执行,执行后要返回结果,返回成功后在发送下一条执行。
参考链接:
https://gorm.io/zh_CN/docs/write_plugins.html
https://studygolang.com/articles/32886?fr=sidebar