初始化项目
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package logSqlSync
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// 错误信息记录表是否已经初始化
|
||||
var ifSyncErrorInfoTableInited bool = false
|
||||
|
||||
// 同步的错误信息处理对象
|
||||
type syncErrorInfo struct {
|
||||
// 数据库连接对象
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// 初始化表信息
|
||||
func (this *syncErrorInfo) init() error {
|
||||
// 初始化表结构
|
||||
if ifSyncErrorInfoTableInited == false {
|
||||
err := this.initTable(this.db)
|
||||
if err == nil {
|
||||
ifSyncErrorInfoTableInited = true
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 把同步信息更新到数据库
|
||||
// data:待更新的数据
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func (this *syncErrorInfo) AddErrorSql(tran *sql.Tx, data string, errMsg string) error {
|
||||
updateSql := "INSERT INTO `sync_error_info` (`SqlString`,`ExecuteTime`,`RetryCount`,`ErrMessage`) VALUES(?,?,?,?);"
|
||||
|
||||
var err error
|
||||
if tran != nil {
|
||||
_, err = tran.Exec(updateSql, data, time.Now(), 0, errMsg)
|
||||
} else {
|
||||
_, err = this.db.Exec(updateSql, data, time.Now(), 0, errMsg)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncErrorInfo.AddErrorSql Error:%s", err.Error()))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化同步信息表结构
|
||||
// db:数据库连接对象
|
||||
func (this *syncErrorInfo) initTable(db *sql.DB) error {
|
||||
// 创建同步信息表
|
||||
createTableSql := `CREATE TABLE IF NOT EXISTS sync_error_info (
|
||||
Id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增Id',
|
||||
SqlString varchar(1024) NOT NULL COMMENT '执行的sql',
|
||||
ExecuteTime datetime NOT NULL COMMENT '最近一次执行时间',
|
||||
RetryCount int NOT NULL COMMENT '重试次数',
|
||||
ErrMessage text NULL COMMENT '执行错误的信息',
|
||||
PRIMARY KEY (Id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='未执行成功的sql数据';`
|
||||
if _, err := db.Exec(createTableSql); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncErrorInfo.initTable Error:%s", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 创建同步信息对象
|
||||
// _db:数据库连接对象
|
||||
// 返回值:
|
||||
// 同步信息对象
|
||||
func newSyncErrorInfoObject(_db *sql.DB) (result *syncErrorInfo, err error) {
|
||||
result = &syncErrorInfo{
|
||||
db: _db,
|
||||
}
|
||||
|
||||
err = result.init()
|
||||
|
||||
return result, err
|
||||
}
|
||||
204
trunk/framework/dataSyncMgr/mysqlSync/logSqlSync/syncObject.go
Normal file
204
trunk/framework/dataSyncMgr/mysqlSync/logSqlSync/syncObject.go
Normal file
@@ -0,0 +1,204 @@
|
||||
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
|
||||
}
|
||||
186
trunk/framework/dataSyncMgr/mysqlSync/logSqlSync/syncingInfo.go
Normal file
186
trunk/framework/dataSyncMgr/mysqlSync/logSqlSync/syncingInfo.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package logSqlSync
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// 同步信息表是否已经被初始化
|
||||
var ifSyncingTableInited bool = false
|
||||
|
||||
// 同步信息项,保存已经处理过的文件的信息
|
||||
type syncingModel struct {
|
||||
// 服务器组Id
|
||||
ServerGroupId int32
|
||||
|
||||
// 待处理文件的绝对路径
|
||||
FilePath string
|
||||
|
||||
// 待处理文件的偏移量
|
||||
FileOffset int64
|
||||
|
||||
// 更新时间
|
||||
UpdateTime time.Time
|
||||
}
|
||||
|
||||
// 同步信息对象
|
||||
type syncingInfo struct {
|
||||
// 服务器组Id
|
||||
ServerGroupId int32
|
||||
|
||||
// 同步信息项
|
||||
item *syncingModel
|
||||
|
||||
// 数据库连接对象
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// 获取同步信息
|
||||
// filePath:正在同步的文件
|
||||
// fileOffset:同步到的位置
|
||||
func (this *syncingInfo) GetSyncingInfo() (filePath string, fileOffset int64) {
|
||||
return this.item.FilePath, this.item.FileOffset
|
||||
}
|
||||
|
||||
// 更新正在同步的位置和文件信息
|
||||
// filePath:文件路径
|
||||
// offset:当前同步到的位置
|
||||
// tran:事务对象,可以为nil
|
||||
// 返回值:
|
||||
// error:处理的错误信息
|
||||
func (this *syncingInfo) Update(filePath string, offset int64, tran *sql.Tx) error {
|
||||
this.item.FilePath = filePath
|
||||
this.item.FileOffset = offset
|
||||
this.item.UpdateTime = time.Now()
|
||||
|
||||
// 更新到数据库
|
||||
return this.update(this.item, tran)
|
||||
}
|
||||
|
||||
// 初始化同步信息
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func (this *syncingInfo) init() error {
|
||||
// 数据表初始化
|
||||
if ifSyncingTableInited == false {
|
||||
if err := this.initSyncingInfoTable(this.db); err == nil {
|
||||
ifSyncingTableInited = true
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 获取此表的同步信息
|
||||
data, exist, err := this.get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. 如果同步信息不存在,则初始化一条到此表
|
||||
if exist == false {
|
||||
data = &syncingModel{
|
||||
ServerGroupId: this.ServerGroupId,
|
||||
FilePath: "",
|
||||
FileOffset: 0,
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
this.item = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// 初始化同步信息表结构
|
||||
// db:数据库连接对象
|
||||
func (this *syncingInfo) initSyncingInfoTable(db *sql.DB) error {
|
||||
// 创建同步信息表
|
||||
createTableSql := `CREATE TABLE IF NOT EXISTS syncing_info (
|
||||
ServerGroupId int NOT NULL COMMENT '服务器组Id',
|
||||
FilePath varchar(500) NOT NULL COMMENT '正在同步的文件路径',
|
||||
FileOffset bigint(20) NOT NULL COMMENT '偏移量',
|
||||
UpdateTime datetime NOT NULL COMMENT '最后一次更新时间',
|
||||
PRIMARY KEY (ServerGroupId)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='正在同步的文件信息';`
|
||||
if _, err := db.Exec(createTableSql); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.initSyncingInfoTable Error:%s", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 从数据库获取数据
|
||||
// 返回值:
|
||||
// data:获取到的数据
|
||||
// exist:是否存在此数据
|
||||
// err:错误信息
|
||||
func (this *syncingInfo) get() (data *syncingModel, exist bool, err error) {
|
||||
//// 从数据库查询
|
||||
querySql := fmt.Sprintf("SELECT FilePath,FileOffset,UpdateTime FROM syncing_info WHERE ServerGroupId ='%v'", this.ServerGroupId)
|
||||
var rows *sql.Rows
|
||||
rows, err = this.db.Query(querySql)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if rows.Next() == false {
|
||||
exist = false
|
||||
return
|
||||
}
|
||||
exist = true
|
||||
|
||||
// 读取数据
|
||||
data = &syncingModel{
|
||||
ServerGroupId: this.ServerGroupId,
|
||||
}
|
||||
err = rows.Scan(&data.FilePath, &data.FileOffset, &data.UpdateTime)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 把同步信息更新到数据库
|
||||
// data:待更新的数据
|
||||
// tran:事务处理对象
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func (this *syncingInfo) update(data *syncingModel, tran *sql.Tx) error {
|
||||
updateSql := "REPLACE INTO `syncing_info` SET `ServerGroupId` = ?, `FilePath` = ?,`FileOffset` = ?, `UpdateTime` = ?;"
|
||||
var err error
|
||||
if tran != nil {
|
||||
_, err = tran.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
|
||||
} else {
|
||||
_, err = this.db.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.update ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建同步信息对象
|
||||
// _dirPath:目录的路径
|
||||
// _identifier:当前数据的唯一标识(可以使用数据库表名)
|
||||
// _db:数据库连接对象
|
||||
// 返回值:
|
||||
// 同步信息对象
|
||||
func newSyncingInfoObject(serverGroupId int32, _db *sql.DB) (result *syncingInfo, err error) {
|
||||
result = &syncingInfo{
|
||||
ServerGroupId: serverGroupId,
|
||||
db: _db,
|
||||
}
|
||||
|
||||
err = result.init()
|
||||
|
||||
return result, err
|
||||
}
|
||||
Reference in New Issue
Block a user