代码拉取完成,页面将自动刷新
package main
import (
"bufio"
"encoding/csv"
"flag"
"io"
"log"
"os"
"regexp"
"strconv"
"strings"
)
type TableDMLNum struct {
Insert int
Update int
Delete int
}
func init() {
file := "./" + "bingo" + ".log"
logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
if err != nil {
panic(err)
}
multiWriter := io.MultiWriter(os.Stdout, logFile)
log.SetOutput(multiWriter)
log.SetFlags(log.LstdFlags | log.LUTC)
return
}
func main() {
// 配置由 mysqlbinlog 解析好的日志文件路径
binlogIn := flag.String("in", "binlog.txt", "binlog source path")
binlogOut := flag.String("out", "binlog.csv", "binlog result file")
flag.Parse()
log.Println("binlog source path: ", *binlogIn)
log.Println("binlog result file: ", *binlogOut)
file, err := os.Open(*binlogIn)
if err != nil {
log.Fatalf("open file failed: %s \n", err.Error())
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Fatalf("close file failed: %s \n", err.Error())
}
}(file)
reader := bufio.NewReader(file)
tableNameNumMap := make(map[string]TableDMLNum)
tableNameNumTransMap := make(map[string]TableDMLNum)
flagInSameTrans := false
tableBeginRex := regexp.MustCompile(".*Table_map:.*mapped to number.*")
tableUpdateRex := regexp.MustCompile("^### UPDATE .*")
tableInsertRex := regexp.MustCompile("^### INSERT INTO .*")
tableDeleteRex := regexp.MustCompile("^### DELETE FROM .*")
tableCommitRex := regexp.MustCompile("^COMMIT\\/\\*\\!\\*\\/;$")
log.Println("Binlog analysis transaction results:")
log.Println("+-------------------------------------------------------------------------------------------+--------------------+--------------------+--------------------+")
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}
if tableBeginRex.Match(line) && !flagInSameTrans {
flagInSameTrans = true
}
if flagInSameTrans && (tableUpdateRex.Match(line) || tableInsertRex.Match(line) || tableDeleteRex.Match(line)) {
if tableUpdateRex.Match(line) {
indexS := strings.Index(string(line), "### UPDATE") + len("### UPDATE") + 1
tableName := strings.TrimSpace(string(line)[indexS:])
if _, ok := tableNameNumTransMap[tableName]; !ok {
tableNameNumTransMap[tableName] = TableDMLNum{Insert: 0, Update: 1, Delete: 0}
} else {
num := tableNameNumTransMap[tableName]
num.Update = num.Update + 1
tableNameNumTransMap[tableName] = num
}
} else if tableInsertRex.Match(line) {
indexS := strings.Index(string(line), "### INSERT INTO") + len("### INSERT INTO") + 1
tableName := strings.TrimSpace(string(line)[indexS:])
if _, ok := tableNameNumTransMap[tableName]; !ok {
tableNameNumTransMap[tableName] = TableDMLNum{Insert: 1, Update: 0, Delete: 0}
} else {
num := tableNameNumTransMap[tableName]
num.Insert = num.Insert + 1
tableNameNumTransMap[tableName] = num
}
} else if tableDeleteRex.Match(line) {
indexS := strings.Index(string(line), "### DELETE FROM") + len("### DELETE FROM") + 1
tableName := strings.TrimSpace(string(line)[indexS:])
if _, ok := tableNameNumTransMap[tableName]; !ok {
tableNameNumTransMap[tableName] = TableDMLNum{Insert: 0, Update: 0, Delete: 1}
} else {
num := tableNameNumTransMap[tableName]
num.Delete = num.Delete + 1
tableNameNumTransMap[tableName] = num
}
}
}
if tableCommitRex.Match(line) {
flagInSameTrans = false
for key, value := range tableNameNumTransMap {
log.Printf("+ Transaction table: %-70s + Insert: %-10d + Update: %-10d + Delete: %-10d + \n", key, value.Insert, value.Update, value.Delete)
if _, ok := tableNameNumMap[key]; ok {
num := tableNameNumMap[key]
num.Update = num.Update + value.Update
num.Insert = num.Insert + value.Insert
num.Delete = num.Delete + value.Delete
tableNameNumMap[key] = num
} else {
tableNameNumMap[key] = TableDMLNum{Insert: value.Insert, Update: value.Update, Delete: value.Delete}
}
}
if len(tableNameNumTransMap) > 0 {
log.Println("+-------------------------------------------------------------------------------------------+--------------------+--------------------+--------------------+")
}
tableNameNumTransMap = make(map[string]TableDMLNum)
}
}
f, err := os.OpenFile(*binlogOut, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
if err != nil {
log.Fatalf("open file failed: %s \n", err.Error())
return
}
writer := csv.NewWriter(f)
var header = []string{"table", "insert", "update", "delete"}
err2 := writer.Write(header)
if err2 != nil {
log.Fatalf("write file failed: %s \n", err2.Error())
return
}
log.Println("Binlog analysis total results:")
log.Println("+--------------------------------------------------------------------------------+--------------------+--------------------+--------------------+")
for key, value := range tableNameNumMap {
log.Printf("+ Total table: %-65s + Insert: %-10d + Update: %-10d + Delete: %-10d + \n", key, value.Insert, value.Update, value.Delete)
log.Println("+--------------------------------------------------------------------------------+--------------------+--------------------+--------------------+")
var data = []string{key, strconv.Itoa(value.Insert), strconv.Itoa(value.Update), strconv.Itoa(value.Delete)}
err3 := writer.Write(data)
if err3 != nil {
log.Fatalf("write file failed: %s \n", err3.Error())
return
}
writer.Flush()
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。