DBから別のデータベースに大量のデータを移行するスクリプトを作成して正常に動作しましたが、現在はゴーリンを使用して同時DB呼び出しを使用してスクリプトを高速化します。ちょうどprocessBatch(offset)
の代わりにgo processBatch(offset)
を呼び出す変更を行ったので、いくつかのゴルーチンが開始されていますが、スクリプトはほぼ即座に終了し、実際には何も行われません。また、起動したゴルーチンの数は、スクリプトを呼び出すたびに変わります。エラーはありません(私が見ることができます)。ゴルーチンのDBコールでエラーが発生してもエラーが発生しない
私はまだgoroutinesとGoに一般的なので、私が間違っているかもしれないことについての指針は非常に高く評価されています。私は変更なしで正常に動作するので、並行処理やDBアクセスに関係しない以下のコードからすべてのロジックを削除しました。私はまた、その行の下の何も実行されないので、失敗したと思うところでコメントを残しました(Printは出力しません)。私もsync.WaitGroupを使ってDBコールをずらしてみましたが、何も変えていないようです。 NADHはコメントで述べたようにmain
関数が終了すると、プログラムが終了したために
var (
legacyDB *sql.DB
v2DB *sql.DB
)
func main() {
var total, loops int
var err error
legacyDB, err = sql.Open("mysql", "...")
if err != nil {
panic(err)
}
defer legacyDB.Close()
v2DB, err = sql.Open("mysql", "...")
if err != nil {
panic(err)
}
defer v2DB.Close()
err = legacyDB.QueryRow("SELECT count(*) FROM users").Scan(&total)
checkErr(err)
loops = int(math.Ceil(float64(total)/float64(batchsize)))
fmt.Println("Total: " + strconv.Itoa(total))
fmt.Println("Loops: " + strconv.Itoa(loops))
for i := 0; i < loops; i++ {
offset := i * batchsize
go processBatch(offset)
}
legacyDB.Close()
v2DB.Close()
}
func processBatch(offset int) {
query := namedParameterQuery.NewNamedParameterQuery(`
SELECT ...
LIMIT :offset,:batchsize
`)
query.SetValue(...)
rows, err := legacyDB.Query(query.GetParsedQuery(), (query.GetParsedParameters())...)
// nothing after this line gets done (Println here does not show output)
checkErr(err)
defer rows.Close()
....
var m runtime.MemStats
runtime.ReadMemStats(&m)
log.Printf("\nAlloc = %v\nTotalAlloc = %v\nSys = %v\nNumGC = %v\n\n", m.Alloc/1024/1024, m.TotalAlloc/1024/1024, m.Sys/1024/1024, m.NumGC)
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
あなたは 'processBatch()'ルーチンを産卵していると
を交換するように見えるが、あなたの 'メインのでしょう'彼らが終わり、ただ終わるのを待たずに。 'sync.WaitGroup'を使って' main() 'がすべてのゴルーチンが終了するのを待つことができます。 – Nadh