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構文の実行結果は、全てデータベースに反映されない。