mysql checksum table golang

package main

import (
	"bytes"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io/ioutil"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

var wg sync.WaitGroup

type DBinfo struct {
	user     string
	pwd      string
	host     string
	port     uint64
	database string
}

type Checkinfo struct {
	host     string
	port     uint64
	database string
	table    string
	checksum uint64
}

func checksumTable(dbinfo *DBinfo, checkinfo *Checkinfo) {
	db := getConn(dbinfo)
	if db == nil {
		return
	}
	defer db.Close()
	tbuf := bytes.Buffer{}
	tbuf.WriteString("checksum table ")
	tbuf.WriteString(checkinfo.table)
	rows, err := db.Query(tbuf.String())
	if err != nil {
		return
	}
	if rows.Next() {
		var table_name string
		var checksum uint64
		rows.Scan(&table_name, &checksum)
		checkinfo.checksum = checksum
	}
}

func getConn(dbinfo *DBinfo) *sql.DB {
	url := bytes.Buffer{}
	url.WriteString(dbinfo.user)
	url.WriteString(":")
	url.WriteString(dbinfo.pwd)
	url.WriteString("@tcp(")
	url.WriteString(dbinfo.host)
	url.WriteString(":")
	url.WriteString(strconv.FormatUint(dbinfo.port, 10))
	url.WriteString(")/")
	url.WriteString(dbinfo.database)
	url.WriteString("?charset=utf8")
	db, err := sql.Open("mysql", url.String())
	if err != nil {
		return nil
	}
	return db
}

func getTables(dbinfo *DBinfo) *map[string]Checkinfo {
	dict := make(map[string]Checkinfo)
	db := getConn(dbinfo)
	if db == nil {
		return nil
	}
	defer db.Close()
	rows, err := db.Query("show tables")
	if err != nil {
		return nil
	}
	for rows.Next() {
		var table_name string
		rows.Scan(&table_name)
		dict[dbinfo.database+"_"+table_name] = Checkinfo{host: dbinfo.host, port: dbinfo.port, database: dbinfo.database, table: table_name}
	}
	return &dict
}

func getDatasource(path string) *map[string]DBinfo {
	dict := make(map[string]DBinfo)
	reg_coll, _ := regexp.Compile(`[/:]+`)
	rf, _ := ioutil.ReadFile(path)
	ar := strings.Split(string(rf), "\n")
	for _, item := range ar {
		ar_coll := reg_coll.Split(item, -1)
		if len(ar_coll) == 5 {
			port, _ := strconv.ParseUint(ar_coll[1], 10, 64)
			dict[ar_coll[2]] = DBinfo{host: ar_coll[0], port: port, database: ar_coll[2], user: ar_coll[3], pwd: ar_coll[4]}
		}
	}
	return &dict
}

func workhandle(skey string, sdbinfo DBinfo, target *map[string]DBinfo) {
	dict := getTables(&sdbinfo)
	if dict != nil {
		for dkey, dcheckinfo := range *dict {
			checksumTable(&sdbinfo, &dcheckinfo)
			//fmt.Println(dkey, "source", dcheckinfo)
			tdbinfo := (*target)[skey]
			tcheckinfo := &Checkinfo{host: tdbinfo.host, port: tdbinfo.port, database: tdbinfo.database, table: dcheckinfo.table}
			checksumTable(&tdbinfo, tcheckinfo)
			//fmt.Println(dkey, "target", tcheckinfo)
			if dcheckinfo.checksum != tcheckinfo.checksum {
				fmt.Println(dkey, "source", dcheckinfo, "->", dkey, "target", tcheckinfo)
			}
		}
	}
	wg.Done()
}
func run() {
	source := getDatasource("/home/work/etc/a.lst")
	target := getDatasource("/home/work/etc/b.lst")
	for skey, sdbinfo := range *source {
		wg.Add(1)
		go workhandle(skey, sdbinfo, target)
	}
	wg.Wait()
}

func main() {
	run()
}



cat /home/work/etc/a.lst 
127.0.0.1:3306/test/xm_dba/123456
127.0.0.1:3306/test_1/xm_dba/123456

cat /home/work/etc/b.lst 
127.0.0.1:3306/test/xm_dba/123456
127.0.0.1:3306/test_1/xm_dba/123456


你可能感兴趣的:(MySQL,golang)