トランザクション

Go標準ライブラリのdatabase/sqlパッケージを利用して、トランザクションを制御する方法を説明します。

トランザクションの利用

Go 1.8以降: database/sqlはContext対応メソッドを提供しています。 このページでは、現在のGoで使いやすいDB.BeginTxTx.ExecContextを前提に説明します。

トランザクションは次のメソッドを使って処理します。

  • DB.BeginTxメソッドでトランザクション開始
  • DB.ExecContextメソッドの代わりにTx.ExecContextメソッドを使ってSQL実行
  • Tx.Commitメソッドでコミット
  • Tx.Rollbackメソッドでロールバック

BeginExecも残っていますが、キャンセルやタイムアウトを扱うコードではContext対応メソッドを使います。

func createTasks(ctx context.Context, db *sql.DB) error {
    // トランザクション開始
    tx, err := db.BeginTx(ctx, nil)
    if err != nil {
        return err
    }
    defer tx.Rollback()

    // SQL1実行
    sqlIns := `INSERT INTO tasks(name, status) VALUES (?, ?);`
    if _, err := tx.ExecContext(ctx, sqlIns, "task1", "open"); err != nil {
        return err
    }

    // SQL2実行
    if _, err := tx.ExecContext(ctx, sqlIns, "task2", "open"); err != nil {
        return err
    }

    // SQL1、SQL2が正常に実行できたらコミット
    return tx.Commit()
}

defer tx.Rollback()を先に設定しておくと、途中でエラーを返した場合にロールバックできます。 tx.Commit()が成功した後に遅延実行されたRollbackは、完了済みのトランザクションには影響しません。