コンセプト
- トランザクション: データベース内のトランザクションは、すべてが成功するかすべてが失敗する、分割できない一連の操作です。この概念により、データの整合性と一貫性が保証されます。
- ロールバック: トランザクション内の 1 つ以上の操作が失敗した場合、ロールバック メカニズムは実行されたすべての操作を元に戻し、データベースをトランザクション開始前の状態に復元します。これはエラー回復メカニズムです。
- コミット: トランザクション内のすべての操作が正常に完了すると、トランザクションはコミットされ、その結果はデータベースに永続的に保存されます。
- ACID 属性:
1) 原子性: トランザクション内のすべての操作が全体として実行されることを確認します。
2) 一貫性: トランザクションの実行により、データベースはある一貫した状態から別の一貫した状態に確実に移行します。
3) 分離: 同時に実行されるトランザクションが互いに独立しており、相互に干渉しないようにします。
4) 耐久性: トランザクションがコミットされると、その結果はデータベースに保持されます。
銀行事件の実務
データの作成
この例では、account_id (主キーとしてのアカウント ID) と Balance (アカウント残高) の 2 つのフィールドを含む、accounts という名前のテーブルを作成します。スクリプトは、それぞれ特定の初期残高を持つ 2 つの口座 A と B を挿入します。
-- 创建银行账户表
CREATE TABLE test.accounts (
account_id VARCHAR(10) PRIMARY KEY,
balance DECIMAL(10, 2) NOT NULL
);
-- 插入初始数据
INSERT INTO test.accounts (account_id, balance) VALUES ('A', 1000.00); -- 假设账户A有1000元
INSERT INTO test.accounts (account_id, balance) VALUES ('B', 500.00); -- 假设账户B有500元
Python スクリプトでのトランザクションのロールバック
次の Python スクリプトは、データベース操作でトランザクションを使用する方法を示しています。スクリプトは connection.begin() で始まり、トランザクションの開始をマークし、2 つのアカウント間の転送の実行を試みます。いずれかの操作が失敗すると例外がトリガーされ、connection.rollback() が実行され、すべての変更が元に戻されます。操作が成功すると、トランザクションは connection.commit() を通じてコミットされます。
import pandas as pd
import pymysql
from credentials import get_credentials
import datetime
def connect_to_database():
credentials = get_credentials()
connection = pymysql.connect(
host='localhost',
user=credentials['username'],
password=credentials['password'],
database='test',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
try:
with connection.cursor() as cursor:
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{current_time} - 开始事务")
connection.begin()
sql_statements = [
"UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A'",
"UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B'",
"select * from accounts;"
]
for sql_statement in sql_statements:
try:
# 执行 SQL 语句
cursor.execute(sql_statement)
# 获取查询结果
result = cursor.fetchall()
df = pd.DataFrame(result)
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{current_time} - 正在执行sql: {sql_statement}")
print(f"{current_time} - 查询结果如下:")
print(df)
except pymysql.MySQLError as e:
# 发生错误时记录错误并准备回滚
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{current_time} - SQL 错误: {e}")
connection.rollback()
print("Transaction rolled back.")
return # 结束函数,不再执行后续操作
# 提交事务
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{current_time} - 提交事务")
connection.commit()
except Exception as e:
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{current_time} - 外部错误: {e}")
connection.rollback()
print("Transaction rolled back.")
finally:
connection.close()
if __name__ == "__main__":
connect_to_database()
さらに、データベース資格情報を安全に管理するために、get_credentials.py モジュールを使用してデータベースのユーザー名とパスワードを保存および取得します。
def get_credentials():
# 替换成你实际的用户名和密码
credentials = {
'username': 'root',
'password': '密码'
}
return credentials
結論: データのセキュリティと整合性を確保する鍵
この記事を通じて、データベース トランザクション処理の中核概念と重要性について深く理解しました。トランザクション、ロールバック、コミットなどの操作はデータベース管理の基礎であるだけでなく、データのセキュリティ、整合性、一貫性を確保するための鍵でもあります。
重要性のまとめ:
- データの整合性: トランザクションにより、エラーやシステム障害が発生した場合でもデータベースの整合性が損なわれないことが保証されます。
- エラー回復: ロールバック メカニズムは、部分的な操作の失敗からデータを保護する効果的なエラー回復パスを提供します。
- 同時実行制御: トランザクションの ACID プロパティは、同時環境でのデータの一貫性と安定性を維持します。