- ベストアンサー
AccessShareLock について気にすべきこと
- AccessShareLockはPostgreSQLのトランザクション内で発生するロックであり、通常のselect文発行時に発生します。
- AccessShareLockはトランザクションの間は維持されるが、解放されていない場合があります。
- AccessShareLockが残っていると、他のトランザクションが更新処理を実行できなくなる可能性があります。commitまたはrollbackを行うことで解放することができます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
回答番号: No.2 に対して訂正があります。 > 手元の psql で確認した限りでは、トランザクション内で SELECT を実 > 行してコミットしていない状態だと、SELECT の対象となっているテーブ > ルの他にいくつかのシステムカタログに対しても Access Share Lock が > 取得されたままでした。 と書きましたが、これは psql 内でテーブル名などの補完を行ったためで した。 いずれにしてもトランザクション内で SELECT を実行してコミットせずに 放置しているのであれば、対象となるテーブルと、そのテーブルに定義さ れたインデックスにも Access Share Lock が取得されたままとなるので、 トランザクションをコミットするようにしてみてください。 トランザクション内で更新していなければロールバックでも構いません。
その他の回答 (2)
- yamada59
- ベストアンサー率74% (29/39)
添付の画像が小さくて気付かなかったのですが (拡大できるのかな?)、クエリーが「<Idle> in transaction」になっているようです。 「<Idle> in transaction」というのはトランザクションが開始されて次の SQL が実行されるのを待っている状態です。 確か JDBC ではデフォルトで自動的にトランザクションが開始され、また、DBCP などのコネクションプールを使っているとデータベースへの接続が保持されたままとなります。 手元の psql で確認した限りでは、トランザクション内で SELECT を実行してコミットしていない状態だと、SELECT の対象となっているテーブルの他にいくつかのシステムカタログに対しても Access Share Lock が取得されたままでした。 従って、Statement オブジェクトの executeQuery メソッドで SELECT を実行した後に Connection オブジェクトの commit メソッドでトランザクションをコミットしてあげれば、大量に Access Share Lock が取得されている状況は解消されるのではないかと思います。
- yamada59
- ベストアンサー率74% (29/39)
ご質問にあるように ACCESS SHARE LOCK は通常の SELECT (FOR UPDATE などを指定していない) を実行した場合に暗黙的に取得されるロックのモードです。従って、ACCESS SHARE LOCK が長時間確保されたままの状態というのは、SELECT の実行に時間がかかっているということです。 ACCESS SHARE LOCK はテーブルロックの中では最も弱いロックなので、残っていたとしてもそれほど問題はありません。問題があるとすれば ACCESS SHARE LOCK と競合する ACCESS EXCLUSIVE を取得する処理、ALTER TABLE、DROP TABLE、TRUNCATE、REINDEX、CLUSTER、VACUUM FULL の実行が待たされることくらいです。 あと、ACCESS SHARE LOCK を開放する方法についてですが、前述のように通常の SELECT を取得されるロックなので、COMMIT や ROLLBACK では対応できません (COMMIT や ROLLBACK が実行されるのは SELECT の実行が完了した後なので)。もし、強制的に ACCESS SHARE LOCK を開放したい場合には SELECT の実行をキャンセルしかありません。
お礼
ご回答どうもありがとうございました。 実際に、select文を発行して結果セットを取得し終わってから放置してみたのですが、20分くらいたってもロックは解放されませんでした。 そして、次のselect文を発行すると、前回のロックが全て解放され、新たなロックが生成され、それがずっと解放されない……という繰り返しになっています。 > 従って、ACCESS SHARE LOCK が長時間確保されたままの状態というのは、SELECT の実行に時間がかかっているということです とのことですが、これはつまり、「selectの終了とはいつのことを指すのか」ということにもつながってくるかと思うのですが、、、 (カテ違いになってしまうかもしれませんが)JDBCで考えると、「selectの終了」とはいつかを考えたとき、思い当たるのは ・executeQuery()メソッドの処理が終わったとき ・結果セットオブジェクト(ResultSet)をクローズしたとき ・ステートメントをクローズしたとき などなどがあるかと思うのですが、実際にはどういうタイミングかご存じでしょうか? よろしくお願いいたします。
お礼
ありがとうございました! 締め切らずに待っていたがありました。。(;-;) なるほどなるほど、やっぱりcommitかrollbackしないといけないのですね。これが残っていると、テストの時などちょっとしたテーブルの修正などができなくてAPサーバーごと停止しないといけないので困っていたのです。 修正箇所が膨大なのでまだ試しておりませんが、きっとこれでうまくいくはずです! どうもありがとうございました!!