Quantcast
Channel: ronSpace
Viewing all articles
Browse latest Browse all 5

PostgreSQL トランザクションの隔離性

$
0
0

PostgreSQL のトランザクションで使用できる隔離性 isolation level は, read committed と, serializable の 2 種類です. これらは, それぞれ, 文単位での読み取り一貫性と, トランザクション単位での読み取り一貫性を保証しようとするものです. 1

さて, 以下のようなテーブル m があります.

mydb=# select * from m;

 m_id | m_name | m_upd_time
------+--------+------------
    1 | foo    |
    2 | bar    |
    3 | baz    |
(3 rows)

ここに, 以下のようなタイミングで, 2 つのトランザクション, Trans1, Trans2 を実行します.

TimeTrans1Trans2
1select from m-
2-update m
3select from m-

すると, それぞれの隔離性に対して, 以下の実行結果が得られます.

------- Read Committed Isolation Level
begin trans2
end trans2
begin trans1
begin select
trans1:bar
end select
begin trans2
end trans2
begin select
trans1:fizzbuzz
end select
end trans1
------- Serializable Isolation Level
begin trans2
end trans2
begin trans1
begin select
trans1:bar
end select
begin trans2
end trans2
begin select
trans1:bar
end select
end trans1

なお, 各隔離性の実行結果について, 先頭の Trans2 の実行は無視してください. テーブル値の初期化に使用しています.

以下は, 実験に使用したソースコード.

###### pg-trans1.rb
###require 'rubygems'
require 'pg'classPgTransdefinitialize(*conn)
    @conn = PGconn.open(*conn)
  enddefx(sql, *rest)
    @conn.exec(sql, *rest)
  end

  private :xendclassTrans1< PgTransdefexecute(is_serial = false)
    begin
      puts 'begin trans1'
      x 'begin'
      x 'set transaction isolation level serializable'if is_serial
      puts 'begin select'
      r = x 'select * from m where m_id = 2'
      r.each {|t| puts "trans1:#{t['m_name']}" }
      puts 'end select'
      sleep 0.2
      puts 'begin select'
      r = x 'select * from m where m_id = 2'
      r.each {|t| puts "trans1:#{t['m_name']}" }
      puts 'end select'
      x 'commit'
      puts 'end trans1'rescue
      x 'rollback'STDERR.puts "pg:#$!"endendendclassTrans2< PgTransdefexecute(mname)
    begin
      puts 'begin trans2'
      x 'begin'
      x "update m set m_name = $1 where m_id = 2", [mname]
      x 'commit'
      puts 'end trans2'rescue
      x 'rollback'STDERR.puts "pg:#$!"endendenddefgo_trans(is_serial)
  Trans2.new(:dbname => 'mydb').execute('bar')
  threads = []
  threads.
    push(Thread.new() doTrans1.new(:dbname => 'mydb').execute(is_serial)
         end
         )
  threads.
    push(Thread.new() doTrans2.new(:dbname => 'mydb').execute('fizzbuzz')
         end
         )
  threads.each {|t| t.join }
end

puts '------- Read Committed Isolation Level'
go_trans(false)
puts '------- Serializable Isolation Level'
go_trans(true)

1.完全に保証するわけではない. 13.2.2.1. Serializable Isolation versus True Serializability, PostgreSQL 8.4.2 Documentation


Viewing all articles
Browse latest Browse all 5

Trending Articles