トランザクションとコンテキストマネージャ
安全にコミットとロールバックを行います
「トランザクションとコンテキストマネージャ」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
トランザクションとは
トランザクションは複数の文をひとまとめにし、すべて成功するか、すべて失敗するようにします。これにより、データの整合性が保たれます。
SQLiteは、データを変更する文の前にトランザクションを自動的に開始します。
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
print('Table ready for transactions')
conn.close()保存するにはコミット
conn.commit()を呼び出すまで、変更は永続化されません。それまでは現在のトランザクション内にだけ存在します。
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
cur.execute('INSERT INTO accounts (balance) VALUES (100)')
conn.commit()
print('Committed')
conn.close()ロールバック
conn.rollback()は、直前のコミット以降に行われたすべての変更を取り消します。問題が発生したときに使用します。
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
conn.commit()
cur.execute('INSERT INTO accounts (balance) VALUES (100)')
conn.rollback()
cur.execute('SELECT COUNT(*) FROM accounts')
print('Rows after rollback:', cur.fetchone()[0])
conn.close()送金
複数の更新を同期させる必要がある場合に、トランザクションは特に役立ちます。銀行振込では、1つの口座から引き落とし、別の口座に入金します。両方を実行するか、どちらも実行しない必要があります。
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 100)')
cur.execute('INSERT INTO accounts (id, balance) VALUES (2, 50)')
cur.execute('UPDATE accounts SET balance = balance - 30 WHERE id = 1')
cur.execute('UPDATE accounts SET balance = balance + 30 WHERE id = 2')
conn.commit()
cur.execute('SELECT id, balance FROM accounts')
print(cur.fetchall())
conn.close()try/exceptによるエラー処理
トランザクションをtry/exceptで囲みます。エラーが発生したらロールバックし、途中までの変更によってデータが壊れないようにします。
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
try:
cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 100)')
cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 200)')
conn.commit()
except sqlite3.IntegrityError:
conn.rollback()
print('Rolled back after error')
conn.close()コンテキストマネージャーとしての接続
with conn:を使うと、成功時には自動的にコミットされ、ブロック内で例外が発生した場合はロールバックされます。
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
with conn:
conn.execute('INSERT INTO accounts (balance) VALUES (100)')
print('Auto-committed via with block')
conn.close()例外発生時の自動ロールバック
with conn:ブロックで例外が発生すると、トランザクションは自動的にロールバックされます。ただし、接続自体は開いたままです。
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY)')
try:
with conn:
conn.execute('INSERT INTO accounts (id) VALUES (1)')
conn.execute('INSERT INTO accounts (id) VALUES (1)')
except sqlite3.IntegrityError:
print('Block rolled back automatically')
count = conn.execute('SELECT COUNT(*) FROM accounts').fetchone()[0]
print('Rows:', count)
conn.close()接続のclosing()
contextlib.closingヘルパーを使うと、ブロックの終了時にclose()が必ず呼び出され、接続が解放されます。
import sqlite3
from contextlib import closing
with closing(sqlite3.connect(':memory:')) as conn:
conn.execute('CREATE TABLE t (id INTEGER)')
print('Used inside closing()')
print('Connection closed automatically')2つのパターンの組み合わせ
closing(...)の内側にwith conn:をネストすると、トランザクションを管理しながら、接続が確実に閉じられるようにできます。
import sqlite3
from contextlib import closing
with closing(sqlite3.connect(':memory:')) as conn:
conn.execute('CREATE TABLE t (id INTEGER, v TEXT)')
with conn:
conn.execute('INSERT INTO t VALUES (1, ?)', ('hello',))
print(conn.execute('SELECT * FROM t').fetchall())isolation_level
接続のisolation_levelは、トランザクションを開始するタイミングを制御します。デフォルトではSQLiteに任せますが、Noneに設定すると自動コミットモードが有効になります。
import sqlite3
conn = sqlite3.connect(':memory:')
print('Default isolation_level:', repr(conn.isolation_level))
conn.isolation_level = None
print('Now autocommit:', conn.isolation_level)
conn.close()トランザクションが重要な理由
トランザクションがないと、更新の途中でクラッシュした場合に、データが中途半端な状態で残る可能性があります。トランザクションは一連の変更をアトミック、つまり分割できない単位にします。これにより、データの整合性が保護されます。
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE log (msg TEXT)')
with conn:
conn.execute('INSERT INTO log VALUES (?)', ('all or nothing',))
print('Atomic write done')
conn.close()確認テスト
トランザクションについての知識を確認しましょう。
まとめ
トランザクションを安全に管理する方法を学びました。
commit()は変更を保存し、rollback()は変更を取り消します- リスクのある書き込みは、ロールバックを行う
try/exceptで囲みます with conn:は自動的にコミットまたはロールバックしますcontextlib.closingは接続が閉じられることを保証します
よくある質問
「トランザクションとコンテキストマネージャ」レッスンは無料ですか?
はい。「トランザクションとコンテキストマネージャ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「トランザクションとコンテキストマネージャ」で何を学びますか?
安全にコミットとロールバックを行います ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「トランザクションとコンテキストマネージャ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 接続とテーブルの作成
- Insert、Select、Update、Delete
- パラメータ化クエリ
- トランザクションとコンテキストマネージャ