最后發(fā)現(xiàn) time.Sleep(100 * time.Millisecond)居然會(huì)影響到數(shù)據(jù)庫(kù)的。去掉之后沒有遇到 busy buffer 的問題了
這兩天將一份數(shù)據(jù)從表1轉(zhuǎn)換到表2,遇到了點(diǎn)問題。
錯(cuò)誤提示:
post total: 2041781
清空 bbs_post 表成功
正在升級(jí) bbs_post 表
正在升級(jí)第 2040031 / 2041781 條 post,錯(cuò)誤: 0errlongDataArr: []
[mysql] 2018/03/31 02:04:52 packets.go:72: read tcp 172.16.0.11:19472->123.207.235.24:3306: read: connection reset by peer
[mysql] 2018/03/31 02:04:52 packets.go:436: busy buffer
轉(zhuǎn)換 bbs_post 表成功,共(2040031)條數(shù)據(jù)
代碼如下:
GitHub: https://github.com/skiy/xiuno...
package xn3ToXn4
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/skiy/xiuno-tools/lib"
"log"
"strings"
"time"
)
type post struct {
db3str,
db4str dbstr
fields postFields
waitFix,
count,
total int
}
type postFields struct {
tid, pid, uid, isfirst, create_date, userip, images, files, message, message_fmt string
}
func (this *post) update() {
if !lib.AutoUpdate(this.db4str.Auto, this.db4str.DBPre+"post") {
return
}
currentTime := time.Now()
err := this.toUpdate(this.waitFix)
if err != nil {
log.Fatalln("轉(zhuǎn)換 " + this.db3str.DBPre + "post 失敗: " + err.Error())
}
this.toUpdate(this.waitFix)
fmt.Printf("轉(zhuǎn)換 %spost 表成功,共(%d)條數(shù)據(jù)\r\n", this.db3str.DBPre, this.count)
fmt.Println("\r\n轉(zhuǎn)換 post 表總耗時(shí): ", time.Since(currentTime))
}
func (this *post) toUpdate(fixFlag int) (err error) {
xn3pre := this.db3str.DBPre
xn4pre := this.db4str.DBPre
xn3db, err := this.db3str.Connect()
query, err := xn3db.Query("select * from " + xn3pre + "post")
if err != nil {
fmt.Println("查詢數(shù)據(jù)庫(kù)失敗", err.Error())
return
}
defer query.Close()
oldField := "tid,pid,uid,isfirst,create_date,userip,images,files,message"
fields := oldField + ",message_fmt"
msgFmtExist := false
cols, _ := query.Columns()
for _, v := range cols {
if v == "message_fmt" {
oldField += ",message_fmt"
msgFmtExist = true
break
}
}
xn3 := fmt.Sprintf("SELECT %s FROM %spost", oldField, xn3pre)
xn5 := fmt.Sprintf("INSERT INTO %spost (%s) VALUES ", xn4pre, fields)
qmark := this.db3str.FieldMakeValue(fields)
qmark2 := this.db3str.FieldMakeQmark(fields, "?")
xn4 := fmt.Sprintf("INSERT INTO %spost (%s) VALUES (%s)", xn4pre, fields, qmark2)
//fmt.Println("Xiuno 3: " + xn3)
//fmt.Println("Xiuno 5: " + xn5)
if fixFlag == 1 {
return this.fixPost(oldField, xn4, msgFmtExist)
}
xn3count := fmt.Sprintf("SELECT COUNT(*) AS count FROM %spost", xn3pre)
rows := xn3db.QueryRow(xn3count)
rows.Scan(&this.total)
fmt.Printf("post total: %d \r\n", this.total)
data, err := xn3db.Query(xn3)
if err != nil {
log.Fatalln(xn3, err.Error())
}
defer data.Close()
xn4db, _ := this.db4str.Connect()
xn4db.SetMaxIdleConns(0)
xn4db.SetMaxOpenConns(100)
xn4db.SetConnMaxLifetime(time.Second * 10)
xn4Clear := "TRUNCATE `" + xn4pre + "post`"
_, err = xn4db.Exec(xn4Clear)
if err != nil {
log.Fatalf(":::清空 %spost 表失敗: "+err.Error(), xn4pre)
}
fmt.Printf("清空 %spost 表成功\r\n", xn4pre)
fmt.Printf("正在升級(jí) %spost 表\r\n", xn4pre)
//dataArr := make([]postFields, ...)
var dataArr []postFields
var longDataArr, errLongDataArr [][]postFields
var sqlStr string
var sqlArr []string
start := 0
times := 0
offset := 50
maxTimes := 50
var field postFields
for data.Next() {
if msgFmtExist {
err = data.Scan(
&field.tid,
&field.pid,
&field.uid,
&field.isfirst,
&field.create_date,
&field.userip,
&field.images,
&field.files,
&field.message,
&field.message_fmt)
} else {
err = data.Scan(
&field.tid,
&field.pid,
&field.uid,
&field.isfirst,
&field.create_date,
&field.userip,
&field.images,
&field.files,
&field.message)
}
if err != nil {
fmt.Printf("獲取數(shù)據(jù)失敗(%s) \r\n", err.Error())
} else {
if field.message_fmt == "" {
field.message_fmt = field.message
}
dataArr = append(dataArr, field)
start++
if start%offset == 0 {
times++
longDataArr = append(longDataArr, dataArr)
dataArr = nil
if times >= maxTimes {
for _, v := range longDataArr {
sqlArr = this.makeFileSql(qmark, v)
sqlStr = xn5 + strings.Join(sqlArr, ",")
_, err = xn4db.Exec(sqlStr)
if err != nil {
fmt.Printf("%d - v - 導(dǎo)入數(shù)據(jù)失敗(%s) \r\n", start, err.Error())
fmt.Println(v)
errLongDataArr = append(errLongDataArr, v)
} else {
this.count += len(v)
lib.UpdateProcess(fmt.Sprintf("正在升級(jí)第 %d / %d 條 post,錯(cuò)誤: %d", this.count, this.total, len(errLongDataArr)))
}
}
times = 0
longDataArr = nil
}
start = 0
}
}
}
if err = data.Err(); err != nil {
log.Fatalln("dataErr: " + err.Error())
}
if dataArr != nil {
sqlArr = this.makeFileSql(qmark, dataArr)
sqlStr = xn5 + strings.Join(sqlArr, ",")
_, err = xn4db.Exec(sqlStr)
if err != nil {
fmt.Printf("dataArr - 導(dǎo)入數(shù)據(jù)失敗(%s) \r\n", err.Error())
errLongDataArr = append(errLongDataArr, dataArr)
}
this.count += len(dataArr)
lib.UpdateProcess(fmt.Sprintf("正在升級(jí)第 %d / %d 條 post,錯(cuò)誤: %d", this.count, this.total, len(errLongDataArr)))
}
fmt.Println("errlongDataArr:", errLongDataArr)
//處理錯(cuò)誤部分的
if errLongDataArr != nil {
stmt, err := xn4db.Prepare(xn4)
if err != nil {
log.Fatalln("處理部分錯(cuò)誤: " + err.Error())
}
start = 0
errCount := 0
for _, values := range errLongDataArr {
for _, value := range values {
start++
fmt.Sprintf("插入錯(cuò)誤序號(hào): %d \r\n", start)
_, err = stmt.Exec(
&value.tid,
&value.pid,
&value.uid,
&value.isfirst,
&value.create_date,
&value.userip,
&value.images,
&value.files,
&value.message,
&value.message_fmt)
if err != nil {
fmt.Printf("導(dǎo)入數(shù)據(jù)失敗(%s) \r\n", err.Error())
errCount++
} else {
this.count++
lib.UpdateProcess(fmt.Sprintf("正在升級(jí)第 %d / %d 條 post,錯(cuò)誤: %d", this.count, this.total, errCount))
}
}
}
}
if err != nil {
log.Fatalln("txErr: " + err.Error())
}
defer xn3db.Close()
defer xn4db.Close()
if this.total-this.count > 0 {
//如果導(dǎo)入部分有失敗的,則修復(fù)
this.waitFix = 1
}
return err
}
func (this *post) fixPost(oldField, xn4 string, msgFmtExist bool) (err error) {
sql := "SELECT " + oldField + " FROM %s WHERE pid NOT IN (SELECT pid FROM %s)"
xn3dbName := this.db3str.DBName + "." + this.db3str.DBPre + "post"
xn4dbName := this.db4str.DBName + "." + this.db4str.DBPre + "post"
xn3sql := fmt.Sprintf(sql, xn3dbName, xn4dbName)
xn3db, err := this.db3str.Connect()
data, err := xn3db.Query(xn3sql)
if err != nil {
fmt.Println("查詢數(shù)據(jù)庫(kù)失敗", err.Error())
return
}
defer xn3db.Close()
if data != nil {
xn4db, err := this.db4str.Connect()
stmt, err := xn4db.Prepare(xn4)
if err != nil {
log.Fatalln("修復(fù)帖子部分錯(cuò)誤: " + err.Error())
}
var field postFields
for data.Next() {
errCount := 0
if msgFmtExist {
err = data.Scan(
&field.tid,
&field.pid,
&field.uid,
&field.isfirst,
&field.create_date,
&field.userip,
&field.images,
&field.files,
&field.message,
&field.message_fmt)
} else {
err = data.Scan(
&field.tid,
&field.pid,
&field.uid,
&field.isfirst,
&field.create_date,
&field.userip,
&field.images,
&field.files,
&field.message)
}
if field.message_fmt == "" {
field.message_fmt = field.message
}
_, err = stmt.Exec(
&field.tid,
&field.pid,
&field.uid,
&field.isfirst,
&field.create_date,
&field.userip,
&field.images,
&field.files,
&field.message,
&field.message_fmt)
if err != nil {
fmt.Printf("PID (%s) 導(dǎo)入數(shù)據(jù)失敗(%s) \r\n", field.pid, err.Error())
errCount++
} else {
this.count++
lib.UpdateProcess(fmt.Sprintf("正在升級(jí)第 %d / %d 條 post,錯(cuò)誤: %d", this.count, this.total, errCount))
}
}
}
return
}
func (this *post) makeFileSql(qmark string, dataArr []postFields) (dataStr []string) {
for _, field := range dataArr {
dataStr = append(dataStr, "("+fmt.Sprintf(qmark,
field.tid,
field.pid,
field.uid,
field.isfirst,
field.create_date,
field.userip,
field.images,
field.files,
field.message,
field.message_fmt)+")")
}
return
}北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問,美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。