トランザクション
コミットとロールバックを行います
「トランザクション」は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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 接続の開始
- 行のクエリ
- プリペアドステートメント
- トランザクション