Dr.Sum でテーブルのインデックス再構築(dwtab_rebuild)を実行した際、次のエラーが発生して処理が失敗しました。
can't acquire table update lock.(test_table:151:exclusive)
@LDBLOCK::TableTypeLock()
@LDDLM3::REBUILD_TABLE
@DBM_TABLE_REBUILD
@LSQLJudge::rebuild_table_stmt
@SQL_Schema_Manipulate_Stmt
@LSQLJudge::sql_schema_stmt
@LSQLJudge::direct_sql_stmt
@LSQLAnalyzer::AnalyzeSQL
@SQLA
@SQL_Translate3
@DBM_Execute
@DBM_Execute
@DWPyDBM::Execute何が起きていたのか
原因は、対象テーブル test_table に対して排他ロック(exclusive lock)が取得できなかったことでした。 dwtab_rebuild はテーブルファイルを丸ごと作り直す処理のため、テーブルに対して完全な排他ロックが必須となります。
今回のバッチは「夜間の誰も参照していない時間帯」に実行していたため、普段はロック競合が起きない前提で運用していました。しかし調査の結果、Datalizer ではなく Enterprise Manager から SQL を実行したセッションが test_table を参照したまま残っていたことが分かりました。 Enterprise Manager で SQL を流した後、セッションを閉じずに残してしまうと、そのセッションが共有ロックを保持し続ける場合があります。そのため、排他ロックが取得できず、再構築処理が開始できませんでした。
Dr.Sum のロック仕様と今回のエラーの関係
Dr.Sum のロックには次の 2 種類があります。
- 共有ロック(shared):SELECT などの参照時に取得されるロック
- 排他ロック(exclusive):UPDATE / DELETE / REBUILD などの更新時に必要なロック
dwtab_rebuild は排他ロックを必要としますが、Enterprise Manager で SQL を実行しているだけでも共有ロックが保持されます。
つまり、
夜間バッチであっても、Enterprise Manager のセッションが残っていると再構築が失敗する可能性がある。
オンライン中はもちろん、夜間でも管理者の作業が残っている可能性があるため注意が必要です。
今回の調査で確認したこと
- Enterprise Manager のセッション一覧で、test_table を参照しているセッションが残っていた
- そのセッションは Enterprise Manager で SQL を流した後、切断されずに残っていた
dwtab_rebuildの lock_mode が 0(即時ロック)で実行されていたため、ロック待ちをせずに即エラーとなった
対応方法と再発防止策
1. lock_mode を 1(継続ロック)に変更して再実行する
ロックが空くまで待機するモードです。
dwtab_rebuild ... 0 1 0ただし、共有ロックが長時間残っている場合は待ち続けるだけで解決しません。
2. Enterprise Manager のセッションを必ず閉じる運用にする
管理者が SQL を流した後、セッションが残り続けることがあるため、作業後に必ず切断することを徹底します。
3. バッチ実行前にセッション一覧を確認する
夜間バッチでも、管理者の作業が残っている可能性があるため、バッチ前にセッション一覧を確認する仕組みを入れると安全です。
4. Datalizer のキャッシュ設定を見直す
キャッシュが効いていれば、テーブルへのロック時間が短くなります。
まとめ
dwtab_rebuildは 排他ロックが必須- Enterprise Manager で SQL を流したセッションが残っていると、
共有ロックが残り続けて再構築が失敗する。 - 夜間バッチでも、管理者の操作が残っているとロック競合が起きるため注意が必要です。
- オンライン中だけでなく、夜間の管理者作業にも気を配る必要があると再認識しました。

コメント