はじめに
今回は課題を進めていくなか、改めて「?」とかんじたトランザクション
と関係するロールバック
について学んだことをアウトプットしたいと思います。
トランザクションとは
- 意味: 一連のデータベース操作を一つのまとまった処理単位として扱うこと
- 特徴: トランザクション内で行われたすべての操作は、すべて成功するか、またはすべて失敗するかのどちらかになる。これをACID特性と呼ぶ
・Atomicity(原子性): 全ての操作が完全に実行されるか、全く実行されないかのどちらか。
・Consistency(一貫性): トランザクションが完了すると、データベースは常に一貫した状態になる。
・Isolation(独立性): 同時に実行されるトランザクションは互いに干渉しない。
・Durability(永続性): トランザクションが完了した後、その結果は永続的に保存される。
ロールバックとは
- 意味: トランザクション内でエラーが発生した場合、トランザクション開始前の状態にデータベースを戻すこと
- 機能: トランザクション内の全ての操作を無効にすることで、データの一貫性を保つ
- 使用することで得られる利点
・データの一貫性の確保: 複数の操作が途中で失敗した場合でも、データベースが不整合な状態になるのを防げる
・エラーハンドリングの簡素化: エラーが発生した場合、ロールバックを行うだけでデータベースの状態を元に戻せる
・信頼性の向上: データベース操作が失敗しても、安全にリカバリできるため、アプリケーション全体の信頼性が向上する
具体例
銀行の送金システムで、以下の2つの操作をトランザクションとして扱うとする
- 送金元の口座から指定金額を引き落とす
- 送金先の口座に指定金額を入金する
もし2番目の操作でエラーが発生した場合、1番目の操作も無効にして元の状態に戻す(ロールバック)ことで、データの一貫性を保つことができる
def transfer_funds(from_account, to_account, amount)
ActiveRecord::Base.transaction do
from_account.decrement!(:balance, amount)
to_account.increment!(:balance, amount)
end
rescue => e
Rails.logger.error("Transfer failed: #{e.message}")
raise ActiveRecord::Rollback
end
このようにトランザクションとロールバックを使用することで、信頼性の高いデータベース操作が実現できる
詳細なシミュレートは次の通り
require 'sequel'
# データベース接続(SQLiteを例に使用)
DB = Sequel.sqlite
# テーブルの作成
DB.create_table :accounts do
primary_key :id
String :name
Float :balance
end
# アカウントモデルの定義
class Account < Sequel::Model
end
# アカウントの初期データを追加
account_a = Account.create(name: 'Aさん', balance: 1000.0)
account_b = Account.create(name: 'Bさん', balance: 500.0)
def transfer(from_account, to_account, amount)
DB.transaction do
# Aさんの口座からお金を引き出す
from_account.update(balance: from_account.balance - amount)
raise "残高不足" if from_account.balance < 0
# Bさんの口座にお金を入れる
to_account.update(balance: to_account.balance + amount)
end
rescue => e
puts "エラー発生: #{e.message}"
raise Sequel::Rollback
end
# 振り込み操作
begin
transfer(account_a, account_b, 200.0)
puts "振り込み成功"
rescue
puts "振り込み失敗"
end
# 結果の確認
puts "Aさんの残高: #{account_a.reload.balance}"
puts "Bさんの残高: #{account_b.reload.balance}"
さいごに
ネットで何でも決済できるようになっていて、具体例のようなトランザクションとロールバックの仕組みの重要性を改めて実感しました。こういうところで活用されているとは…
私もいつか世の中のためになるようなものをつくりたいです