トランザクション
トランザクションとは、関連のあるデータベースの更新処理を一つにまとめたもの。BEGINでトランザクション処理を開始し、COMMITで一連の更新処理の結果をデータベースに反映する。また途中で問題が生じた場合はROLLBACKでデータベースをトランザクション処理を行う前の状態に戻すことができる。これらのことにより、全て成功するか、全て失敗するかの二択であることが保証され、データの整合性を保つことができる。
sqlite3-rubyでトランザクション処理を行うには以下のようにする。
db.transaction # トランザクションを開始する begin db.execute('insert into test_a values(?, ?)', *data_a) db.execute('insert into test_b values(?, ?)', *data_b) db.execute('insert into test_c values(?, ?)', *data_c) db.commit # 処理を確定する rescue db.rollback # 例外が発生したら処理を取り消す end
ブロックを使って書くこともできる。
db.transaction do db.execute('insert into test_a values(?, ?)', *data_a) db.execute('insert into test_b values(?, ?)', *data_b) db.execute('insert into test_c values(?, ?)', *data_c) end
本当に例外が発生したら処理が取り消されるか試してみる。
#!/usr/bin/ruby require 'sqlite3' def transaction_test(data) db = SQLite3::Database.new('test.db') db.execute('delete from test') begin db.transaction do data.each do |d| raise if d.nil? db.execute('insert into test values(?, ?)', *d) end puts 'insert ok' end rescue => e puts 'insert error' end db.close db = SQLite3::Database.new('test.db') p db.execute('select * from test') end data = [ ['b', 'b@hoge.com'], ['c', 'c@hoge.com'], ['d', 'd@hoge.com'], ] transaction_test(data) puts transaction_test(data << nil)
insert ok [["b", "b@hoge.com"], ["c", "c@hoge.com"], ["d", "d@hoge.com"]] insert error []