お世話になっております。
しゃまとんです。
webの開発をやっていると、データベースは切っても切れないものだと思います。
自分はMySQLを使うことが多いのですが、最近MySQLを使った開発を行っているときにトランザクション管理ちゃんとしないとなと思い考えていた時、
MySQLで空コミットしたときって処理重くなるのかな・・・?
と思い、すこし調べてみました。
(webでググっても、サクッとでてこなかった)
簡単に処理を何個か作成しループを100回させてみました。
申し訳ないですが、自分はそこまで精通している人間ではないので、参考程度に読んでいただけると幸いです。
言語にはgoを使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
package main import ( "database/sql" "log" "time" _ "github.com/go-sql-driver/mysql" ) type User struct { Id int32 Name string Score int32 } const loop = 100 func main() { cnn, _ := sql.Open("mysql", "user:pass@tcp(localhost:port)/database") defer cnn.Close() // txなしselect f1 := func() { var user User if err := cnn.QueryRow("SELECT id, name, score FROM user WHERE id = ? LIMIT 1", 1).Scan(&user.Id, &user.Name, &user.Score); err != nil { log.Fatal(err) } } latency1 := exec(f1) log.Println("f1 : ", latency1) // txありselect f2 := func() { tx, _ := cnn.Begin() var user User if err := tx.QueryRow("SELECT id, name, score FROM user WHERE id = ? LIMIT 1", 1).Scan(&user.Id, &user.Name, &user.Score); err != nil { log.Fatal(err) } tx.Commit() } latency2 := exec(f2) log.Println("f2 : ", latency2) // updateレコード変更なし f3 := func() { tx, _ := cnn.Begin() if _, err := tx.Exec("UPDATE user SET score = score WHERE id = ?", 1); err != nil { log.Fatal(err) } tx.Commit() } latency3 := exec(f3) log.Println("f3 : ", latency3) // update レコード変更ありrollback f4 := func() { tx, _ := cnn.Begin() if _, err := tx.Exec("UPDATE user SET score = score + 1 WHERE id = ?", 1); err != nil { log.Fatal(err) } tx.Rollback() } latency4 := exec(f4) log.Println("f4 : ", latency4) // update レコード変更ありcommit f5 := func() { tx, _ := cnn.Begin() if _, err := tx.Exec("UPDATE user SET score = score + 1 WHERE id = ?", 1); err != nil { log.Fatal(err) } tx.Commit() } latency5 := exec(f5) log.Println("f5 : ", latency5) } func exec(f func()) time.Duration { t := time.Now() for i := 0; i < loop; i++ { f() } latency := time.Since(t) return latency } |
結果は下記のようになりました。
見た感じですと
select(txなし) << select(txあり) <= update(空コミット) << update(commit) <= update(rollback)
となりました。selectの速度差はトランザクション開始の処理が入っているので当然なのですが、oracleの空コミットと同様に何も処理されない(?)ので、select(txあり)とほぼ変わらないっぽいですね。
勉強になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ go run main.go f1 : 32.243891ms f2 : 46.160667ms f3 : 50.834508ms f4 : 83.56319ms f5 : 76.303116ms --- f1 : 33.905533ms f2 : 46.795762ms f3 : 54.755387ms f4 : 84.56939ms f5 : 74.385792ms --- f1 : 33.64808ms f2 : 46.192082ms f3 : 52.673612ms f4 : 85.065523ms f5 : 80.058726ms --- f1 : 32.868818ms f2 : 51.224252ms f3 : 51.798962ms f4 : 81.424738ms f5 : 71.117165ms --- f1 : 33.805161ms f2 : 45.889625ms f3 : 50.216731ms f4 : 78.674484ms f5 : 78.635478ms |