205 lines
4.6 KiB
Go
205 lines
4.6 KiB
Go
package logSqlSync
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"Framework/dataSyncMgr/mysqlSync/sqlSync"
|
|
"goutil/logUtil"
|
|
)
|
|
|
|
// 同步对象定义
|
|
type SyncObject struct {
|
|
// 服务器组Id
|
|
serverGroupId int32
|
|
|
|
// 同步数据的存储路径
|
|
dirPath string
|
|
|
|
// 同步数据对象的唯一标识,用于进行重复判断
|
|
identifier string
|
|
|
|
// 数据库对象
|
|
dbObj *sql.DB
|
|
|
|
// 同步信息对象
|
|
syncingInfoObj *syncingInfo
|
|
|
|
// 错误处理对象
|
|
errorHandleObj *syncErrorInfo
|
|
|
|
// 同步对象
|
|
syncObj *sqlSync.SyncObject
|
|
}
|
|
|
|
// 初始化
|
|
// baseObj:基础同步对象
|
|
func (this *SyncObject) Init(baseObj *sqlSync.SyncObject) {
|
|
this.syncObj = baseObj
|
|
|
|
// 初始化同步信息对象
|
|
syncingInfoObj, err := newSyncingInfoObject(this.serverGroupId, this.dbObj)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
//// 初始化错误处理对象
|
|
errorHandleObj, err := newSyncErrorInfoObject(this.dbObj)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
this.syncingInfoObj = syncingInfoObj
|
|
this.errorHandleObj = errorHandleObj
|
|
|
|
// 初始化当前处理的文件
|
|
fileList := sqlSync.GetDataFileList(this.dirPath)
|
|
filePath, _ := this.syncingInfoObj.GetSyncingInfo()
|
|
if len(filePath) < 0 && len(fileList) > 0 {
|
|
this.syncingInfoObj.Update(fileList[0], 0, nil)
|
|
}
|
|
}
|
|
|
|
// 获取正在同步的信息
|
|
// filePath:文件路径
|
|
// offset:文件偏移量
|
|
func (this *SyncObject) GetSyncingInfo() (filePath string, offset int64) {
|
|
return this.syncingInfoObj.GetSyncingInfo()
|
|
}
|
|
|
|
// 更新
|
|
// filePath:文件路径
|
|
// offset:文件偏移量
|
|
// tran:事务对象
|
|
// 返回值:
|
|
// error:错误对象
|
|
func (this *SyncObject) Update(filePath string, offset int64, tx *sql.Tx) error {
|
|
return this.syncingInfoObj.Update(filePath, offset, tx)
|
|
}
|
|
|
|
// 同步一条sql语句
|
|
// command:待执行的命令
|
|
// filePath:保存路径
|
|
// offset:文件偏移量
|
|
// 返回值:
|
|
// error:错误信息
|
|
func (this *SyncObject) SyncOneSql(command string, filePath string, offset int64) {
|
|
var err error
|
|
for {
|
|
err = sqlSync.ExecuteByTran(this.dbObj, func(tran *sql.Tx) (isCommit bool, err error) {
|
|
// 保存sql到数据库
|
|
err = this.syncToMysql(command, tran)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 保存进度信息到数据库
|
|
err = this.syncingInfoObj.Update(filePath, offset, tran)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
isCommit = true
|
|
return
|
|
})
|
|
|
|
// 如果是连接出错,则仍然循环执行
|
|
if err != nil {
|
|
if sqlSync.CheckIfConnectionError(err.Error()) {
|
|
time.Sleep(5 * time.Second)
|
|
continue
|
|
}
|
|
}
|
|
|
|
// 如果不是数据库连接出错,则算是执行完成
|
|
break
|
|
}
|
|
|
|
// 如果存在错误,则循环尝试执行
|
|
if err != nil {
|
|
this.recordSqlError(command, filePath, offset, err.Error())
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 同步数据到mysql中
|
|
// command:sql语句
|
|
// tx:事务处理对象
|
|
// 返回值:
|
|
// error:错误信息
|
|
func (this *SyncObject) syncToMysql(command string, tx *sql.Tx) error {
|
|
_, err := tx.Exec(command)
|
|
if err != nil {
|
|
logUtil.ErrorLog(fmt.Sprintf("mysqlSync/logSqlSync/syncObject.syncToMysql error:%s", err.Error()))
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 错误处理
|
|
// cmd:待执行的命令
|
|
// filePath:保存路径
|
|
// offset:文件偏移量
|
|
// errMsg:错误信息
|
|
func (this *SyncObject) recordSqlError(command string, filePath string, offset int64, errMsg string) {
|
|
errMsg = sqlSync.GetSimpleErrorMessage(errMsg)
|
|
|
|
for {
|
|
err := sqlSync.ExecuteByTran(this.dbObj, func(tran *sql.Tx) (isCommit bool, err error) {
|
|
// 保存sql到数据库
|
|
err = this.errorHandleObj.AddErrorSql(tran, command, errMsg)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 保存进度信息到数据库
|
|
err = this.syncingInfoObj.Update(filePath, offset, tran)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
isCommit = true
|
|
return
|
|
})
|
|
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
time.Sleep(5 * time.Second)
|
|
}
|
|
}
|
|
|
|
// 创新新的mysql同步对象
|
|
// dirPath:存放数据的目录
|
|
// identifier:当前数据的唯一标识(可以使用数据库表名)
|
|
// dbObj:数据库对象
|
|
// syncingInfoObj:同步信息记录对象
|
|
// errorHandleObj:错误处理对象
|
|
// 返回值:
|
|
// mysql同步对象
|
|
func NewSyncObject(serverGroupId int32, dirPath, identifier string, dbObj *sql.DB) *SyncObject {
|
|
dirPath = filepath.Join(dirPath, identifier)
|
|
|
|
// 创建更新目录
|
|
err := os.MkdirAll(dirPath, os.ModePerm|os.ModeTemporary)
|
|
if err != nil {
|
|
err = fmt.Errorf("%s-%s-make dir failed:%s", identifier, "SyncObject.newSyncObject.os.MkdirAll", err)
|
|
logUtil.ErrorLog(err.Error())
|
|
panic(err)
|
|
}
|
|
|
|
// 构造同步信息对象
|
|
result := &SyncObject{
|
|
serverGroupId: serverGroupId,
|
|
dirPath: dirPath,
|
|
identifier: identifier,
|
|
dbObj: dbObj,
|
|
}
|
|
|
|
return result
|
|
}
|