FC2ブログ

徒然さめざめ

思ったことを思ったときに思ったように

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

rails と connection pool とついでに スレッド と

rails2.2以降に connection pool が組み込まれたわけだが、
いまいちどこにも関係性を示した情報がない。

というかスレッド使用時にpoolが枯渇してしまうという問題がでた。

なので、がっつり調べてみた。

実態は以下のファイルなので
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_pool.rb
これに標準出力するものをいれて確認してみた。


@@ -64,6 +64,7 @@
#
# The default ConnectionPool maximum size is 5.
def initialize(spec)
+ pp caller
@spec = spec

# The cache of reserved connections mapped to threads
@@ -179,6 +180,9 @@
# - ConnectionTimeoutError: no connection can be obtained from the pool
# within the timeout period.
def checkout
+ puts "checkout"
+ puts @size
+ puts @connections.size
# Checkout an available connection
@connection_mutex.synchronize do
loop do



まずscript/consoleを起動


$ ruby script/console
Loading development environment (Rails 2.3.4)
["/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:300:in `new'",
"/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:300:in `establish_connection'",
"/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_specification.rb:57:in `establish_connection'",
"/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_specification.rb:86:in `establish_connection'",
"/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_specification.rb:60:in `establish_connection'",
"/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_specification.rb:55:in `establish_connection'",
"/usr/lib/ruby/gems/1.8/gems/rails-2.3.4/lib/initializer.rb:438:in `initialize_database'",
"/usr/lib/ruby/gems/1.8/gems/rails-2.3.4/lib/initializer.rb:141:in `process'",
"/usr/lib/ruby/gems/1.8/gems/rails-2.3.4/lib/initializer.rb:113:in `send'",
"/usr/lib/ruby/gems/1.8/gems/rails-2.3.4/lib/initializer.rb:113:in `run'",
"dbtest/config/environment.rb:13",
"/usr/lib/ruby/1.8/irb/init.rb:252:in `require'",
"/usr/lib/ruby/1.8/irb/init.rb:252:in `load_modules'",
"/usr/lib/ruby/1.8/irb/init.rb:250:in `each'",
"/usr/lib/ruby/1.8/irb/init.rb:250:in `load_modules'",
"/usr/lib/ruby/1.8/irb/init.rb:21:in `setup'",
"/usr/lib/ruby/1.8/irb.rb:54:in `start'",
"/usr/bin/irb:13"]


connection poolが呼ばれている。

次にmodelからデータベースにアクセス


>> Foo.first
checkout
5
0
=> #<Foo id: 1, name: nil, bar_id: nil, f_test: nil, created_at: "2009-12-03 07:24:20", updated_at: "2009-12-03 07:24:20">



pool からチェックアウトされた。

次に同じモデルや別のモデルも読んでみる


>> Foo.first
=> #<Foo id: 1, name: nil, bar_id: nil, f_test: nil, created_at: "2009-12-03 07:24:20", updated_at: "2009-12-03 07:24:20">
>> Foo.first
=> #<Foo id: 1, name: nil, bar_id: nil, f_test: nil, created_at: "2009-12-03 07:24:20", updated_at: "2009-12-03 07:24:20">
>> Foo.first
=> #<Foo id: 1, name: nil, bar_id: nil, f_test: nil, created_at: "2009-12-03 07:24:20", updated_at: "2009-12-03 07:24:20">
>> Bar.first
:overridden!
=> nil


pool から チェックアウト されない。

ということは、この時点で pool に接続し続けているということだ。

ここでconnection poolの状態を確認


pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb781f42c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>],
@connection_mutex=
#<Monitor:0xb781bffc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>],
@queue=
#<MonitorMixin::ConditionVariable:0xb781bf70
@monitor=
#<Monitor:0xb781bffc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-604243748=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb787357c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


ActiveRecord::ConnectionAdapters::MysqlAdapter が、connectionsとchecked_outに同じものがある

では1プロセスの中でどうすればチェックアウトを増やすことができるのか。
(というよりどういうときにコネクション数が増えてしまうか?)

結論からいうとスレッドを使ってみたら増えた。


>> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76bf0b4 sleep>
>>
5
1
#<Foo:0xb76bd4bc>


# スレッドなので表示がおかしいのはスルーの方向で

新たにチェックアウトされたことを確認できる。

さらに増やしてみる


>> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76bf0b4 sleep>
>>
5
1
#<Foo:0xb76bd4bc>

?> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76b6388 sleep>
>>
5
2
#<Foo:0xb76b47a4>

?> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76b265c sleep>
>>
5
3
#<Foo:0xb76b0a78>

?> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76ae930 sleep>
>>
5
4
#<Foo:0xb76acd4c>

?> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76aac04 sleep>
>>
5
5

?> Thread.start{ puts Foo.first}
checkout=> #<Thread:0xb76a82ec sleep>
>>
5
5

?> #<Foo:0xb76a6460>#<Foo:0xb76a62f8>


デフォルトの設定では上限5個なので5以上は増えない

では、この時のプールの状態は...

pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb781f42c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76bde94
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76be7b8>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.404834747314453>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b517c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b5aa0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.370025634765625>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b1450
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b1d74>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.403165817260742>],
@connection_mutex=
#<Monitor:0xb781bffc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76bde94
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76be7b8>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.404834747314453>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b517c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b5aa0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.370025634765625>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b1450
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b1d74>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.403165817260742>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76ad724
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76ae048>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.303268432617188>],
@queue=
#<MonitorMixin::ConditionVariable:0xb781bf70
@monitor=
#<Monitor:0xb781bffc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-608872958=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76bde94
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76be7b8>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.404834747314453>,
-604243748=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76e636c
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76e780c>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=3.082275390625>,
-608886578=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b1450
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b1d74>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.403165817260742>,
-608878218=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb76b517c
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76b5aa0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb79b0390
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb799e85c>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.370025634765625>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb787357c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


checked_out と reserved_connections は4個ずつ
ActiveRecord::ConnectionAdapters::MysqlAdapter を持っているが
connections だけ5個持っている。

4個しか持っていない意味はよくわからない。#ダレか教えて!

つまるところ、同時に複数(poolの設定上限数を超える)のスレッドを作ってしまうと
そしてpoolを使いきってしまうわけだ。

poolを解放するにはどうしたらいいのだろうか。

connection_pool.rb をみると、


# Signal that the thread is finished with the current connection.
# #release_connection releases the connection-thread association
# and returns the connection to the pool.
def release_connection
conn = @reserved_connections.delete(current_connection_id)
checkin conn if conn
end


というのがあった。
おぉ!まさにこれじゃね?ってことで試してみる。

あらためてconsoleを起動

初期のpoolの状態

?> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=[],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=[],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections={},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


connectionsもchecked_outも0

チェックアウトする。


>> Foo.first
checkout
5
0
=> #<Foo id: 1, name: nil, bar_id: nil, f_test: nil, created_at: "2009-12-03 07:24:20", updated_at: "2009-12-03 07:24:20">
>> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-604460838=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


1個ずつ増える。

スレッドの中でrelease_connectionを試してみる。


>> Thread.start{Foo.first;ActiveRecord::Base.connection_pool.release_connection;}
checkout=> #<Thread:0xb76870ec sleep>
>>
5
1

?> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7685ee0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7686804>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.297069549560547>],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-604460838=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


くりかえす


>> Thread.start{Foo.first;ActiveRecord::Base.connection_pool.release_connection;}
=> #<Thread:0xb763ca88 run>
>> checkout
5
2

>> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7685ee0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7686804>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=0.436067581176758>],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-604460838=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


面倒くさくなったのでloopで回しまくる。


>> loop {Thread.start{Foo.first;ActiveRecord::Base.connection_pool.release_connection;}}


結果


?> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7685ee0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7686804>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=24.9977111816406>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7610424
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7610d48>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=23.2257843017578>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb760dfd0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb760e8f4>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=26.6613960266113>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb760b94c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb760c270>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=22.395133972168>],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections=
{-604460838=>
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config=
{:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil



わかるだろうか?

checked_outの数は最初にスレッドを使わずにアクセスしたモノだけとなっている。

これで、スレッド使用時のpool枯渇問題に対応できるのではないだろうか?

最後の確認


>> ActiveRecord::Base.connection_pool.release_connection
=> nil
>> pp ActiveRecord::Base.connection_pool
#<ActiveRecord::ConnectionAdapters::ConnectionPool:0xb77b5a2c
@checked_out=[],
@connection_mutex=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@connections=
[#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7640340
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb76417e0>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=2.49075889587402>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7685ee0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7686804>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=24.9977111816406>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7610424
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb7610d48>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=23.2257843017578>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb760dfd0
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb760e8f4>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=26.6613960266113>,
#<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb760b94c
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"},
@connection=#<Mysql:0xb760c270>,
@connection_options=[nil, "root", "", "db_test", nil, nil],
@last_verification=0,
@logger=
#<ActiveSupport::BufferedLogger:0xb7946a1c
@auto_flushing=1,
@buffer={},
@guard=#<Mutex:0xb7934e84>,
@level=0,
@log=#<File:/home/hoge/dbtest/log/development.log>>,
@query_cache_enabled=false,
@quoted_column_names={"foos"=>"`foos`"},
@quoted_table_names={"foos"=>"`foos`"},
@runtime=22.395133972168>],
@queue=
#<MonitorMixin::ConditionVariable:0xb77b2570
@monitor=
#<Monitor:0xb77b25fc
@mon_count=0,
@mon_entering_queue=[],
@mon_owner=nil,
@mon_waiting_queue=[]>,
@waiters=[]>,
@reserved_connections={},
@size=5,
@spec=
#<ActiveRecord::Base::ConnectionSpecification:0xb7809b7c
@adapter_method="mysql_connection",
@config={:database=>"db_test", :adapter=>"mysql", :pool=>5, :user=>"root"}>,
@timeout=5>
=> nil


checked_outが全部消えたよ!
スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://fmkt.blog65.fc2.com/tb.php/138-2552a1b7
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。