Go言語とSQLiteで下記のコードをトランザクションしてみる。
トランザクションとは、分割不可な一連の処理を意味する。
今回は、user_id=1のpriceから1000円を引き、user_id=2のpriceに1000円たすという処理を行うが、この時、途中でエラーが起こった場合は、どの処理もされないようにしたい。この時にトランザクションの仕組みを利用する。
package main
import (
"database/sql"
"log"
"strconv"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "sample.db")
if err != nil {
log.Fatal(err)
}
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
/** ここからuser_idが1のpriceから1000を引いて更新する処理 **/
rows, _ := tx.Query("SELECT price FROM calc WHERE user_id=1;")
var price int
for rows.Next() {
err = rows.Scan(&price)
if err != nil {
log.Fatal(err)
}
}
price = price - 1000
newprice := strconv.Itoa(price)
t := "UPDATE calc SET price = " + newprice + " WHERE user_id=1"
_, err = tx.Exec(t)
if err != nil {
log.Fatal(err)
}
/** ここまでuser_idが1のpriceから1000を引いて更新する処理 **/
/** ここからuser_idが2のpriceから1000を足して更新する処理 **/
rows, _ = tx.Query("SELECT price FROM calc WHERE user_id=2;")
defer rows.Close()
for rows.Next() {
err = rows.Scan(&price)
if err != nil {
log.Fatal(err)
}
}
price = price + 1000
newprice = strconv.Itoa(price)
t = "UPDATE calc SET price = " + newprice + " WHERE user_id=2"
_, err = tx.Exec(t)
if err != nil {
log.Fatal(err)
}
/** ここまでuser_idが2のpriceから1000を足して更新する処理 **/
tx.Commit()
}
sql.Openした後、tx, err := db.Begin()でトランザクションを開始する。これ以降dbをtx表記しなければならない。
最後にtx.Commit()でトランザクションを終了する。
tx.Commitの前に一度でもエラーがあって処理がとまった場合は、エラー前に行われたSQL構文の実行結果は、全てデータベースに反映されない。




