0Pricing
Go Academy · レッスン

トランザクション

コミットとロールバックを行います

「トランザクション」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

トランザクションを使う理由

トランザクションは複数のステートメントをまとめ、それらをすべて成功させるか、すべて失敗させます。たとえば、途中で失われることなく2つの口座間で送金できるように、データの整合性を保ちます。

  • 原子性:すべて実行されるか、何も実行されない
  • 一貫性のある状態
  • 他のトランザクションから分離される

db.Begin

Begin はトランザクションを開始し、*sql.Tx を返します。ステートメントはプールではなくTx上で実行します。そうすることで、1つのコネクションと1つのトランザクションを共有できます。

tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}

Tx上でのステートメント実行

db上の場合と同じように tx.Exec と tx.Query を呼び出せます。ただし、コミットまたはロールバックするまでは、すべての処理がトランザクション内で実行されます。

_, err = tx.Exec("UPDATE accounts SET balance = balance - $1 WHERE id = $2", 100, 1)

コミット

tx.Commit() はすべての変更を永続化し、他の処理から見えるようにします。エラーが返された場合、トランザクションは適用されていません。

if err := tx.Commit(); err != nil {
    log.Fatal(err)
}

ロールバック

いずれかの手順が失敗した場合は、tx.Rollback() を呼び出してBegin以降のすべての変更を破棄します。データベースは、何も起きなかったかのように以前の状態へ戻ります。

if err != nil {
    tx.Rollback()
    return err
}

defer Rollbackパターン

堅牢なイディオムでは、Beginの直後にRollbackをdeferします。Commitが成功した後のRollbackは安全な何もしない処理になるため、どのエラーパスでも確実に後処理できます。

tx, err := db.Begin()
if err != nil { return err }
defer tx.Rollback()
// ... do work ...
return tx.Commit()

原子的な送金の例

2つの更新で1つの論理的な処理を構成します。1つの口座から差し引き、別の口座に加算します。両方をまとめてコミットするか、どちらも適用しない必要があります。

実行可能なトランザクションのシミュレーション

実際のトランザクションにはデータベースが必要です。この実行可能な例では、メモリ上のmapを使って、開始、2つの更新、コミットまたはロールバックをシミュレートします。

package main

import (
    "errors"
    "fmt"
)

func transfer(bal map[string]int, from, to string, amt int) error {
    if bal[from] < amt {
        return errors.New("insufficient funds")
    }
    snapshot := map[string]int{from: bal[from], to: bal[to]}
    bal[from] -= amt
    bal[to] += amt
    if bal[from] < 0 {
        bal[from], bal[to] = snapshot[from], snapshot[to]
        return errors.New("rolled back")
    }
    return nil
}

func main() {
    bal := map[string]int{"alice": 100, "bob": 20}
    if err := transfer(bal, "alice", "bob", 30); err != nil {
        fmt.Println("error:", err)
    } else {
        fmt.Println("committed:", bal)
    }
}

分離レベル

db.BeginTx では、sql.LevelSerializable のような分離レベルを含むオプションを指定できます。分離レベルを高くすると多くの異常を防げますが、同時実行性が低下する可能性があります。

tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})

トランザクションは短く保つ

トランザクションはコネクションを保持し、ロックも保持する可能性があります。SQL処理はすべて速やかに行い、内部でのネットワーク呼び出しやユーザー入力を避け、競合を減らすためにすぐコミットしてください。

dbとtxを混在させない

トランザクション内では、ステートメントを tx 上でのみ実行してください。そこで db.Exec を呼び出すと、トランザクション外の別のコネクションが使われるため、その変更はトランザクションに含まれず、ロールバックもされません。

理解度チェック

トランザクションに関する知識を確認しましょう。

まとめ

トランザクションについて学びました。

  • Beginは*sql.Txを返し、その上でステートメントを実行します
  • Commitは変更を永続化し、Rollbackはすべての変更を破棄します
  • defer tx.Rollback()によって、エラー時の後処理を保証できます
  • BeginTxで分離レベルを設定し、トランザクションは短く保ちます
  • 1つのトランザクション内でdbとtxを混在させません

よくある質問

「トランザクション」レッスンは無料ですか?

はい。「トランザクション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「トランザクション」で何を学びますか?

コミットとロールバックを行います ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「トランザクション」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 接続の開始
  2. 行のクエリ
  3. プリペアドステートメント
  4. トランザクション
← Go Academyに戻る