goodbyegangsterのブログ

備忘録的な

Redshiftにおけるロックの概念

Redshiftにおけるロックの考え方について、まとめておきます。以下は参考となるAWSナレッジのサイトです。

Amazon Redshift でのクエリのブロックを防ぐ方法

Redshiftの分離レベル

まず、Redshiftの分離レベルは、 SERIALIZABLE となっています。基本的な4つの分離レベルの中で、最も強い分離レベルですね。以下はおさらい。

許容する現象 SERIALIZABLE REPEATABLE READ READ COMMITTED READ UNCOMMITTED
ファントムリード
非再現リード
ダーティ・リード

現象について。

  • ファントムリード
  • 非再現リード
  • ダーティ・リード
    • 未commitの値を読んじゃう

Redshiftのロックの種類

で、実際にRedshiftにおけるロックの種類ですが、行ロックの概念はありません。表ロックのみ用意されています。用意されているロックの種類は、以下の3つがあります。

  • AccessExclusiveLock
    • 主にDDL (ALTER TABLE、DROP、TRUNCATEなど) により取得
    • すべてのロック試行をブロック
  • AccessShareLock
    • UNLOAD、SELECT、UPDATE、またはDELETEにより取得
    • AccessExclusiveLock試行のみをブロック
  • ShareRowExclusiveLock
    • COPY、INSERT、UPDATE、またはDELETEにより取得
    • AccessExclusiveLockと、その他のShareRowExclusiveLock試行をブロック

まとめるとこんな感じです。

AccessExclusiveLock AccessShareLock ShareRowExclusiveLock
AccessExclusiveLock ブロック ブロック ブロック
AccessShareLock ブロック
ShareRowExclusiveLock ブロック ブロック

ロックを保持しているセッションを確認

実際にロックしているセッションは、以下のSQLにて確認可能です。SuperUserで実行。

select a.txn_owner, a.txn_db, a.xid, a.pid, a.txn_start, a.lock_mode, a.relation as table_id,nvl(trim(c."name"),d.relname) as tablename, a.granted,b.pid as blocking_pid ,datediff(s,a.txn_start,getdate())/86400||' days '||datediff(s,a.txn_start,getdate())%86400/3600||' hrs '||datediff(s,a.txn_start,getdate())%3600/60||' mins '||datediff(s,a.txn_start,getdate())%60||' secs' as txn_duration
from svv_transactions a 
left join (select pid,relation,granted from pg_locks group by 1,2,3) b 
on a.relation=b.relation and a.granted='f' and b.granted='t' 
left join (select * from stv_tbl_perm where slice=0) c 
on a.relation=c.id 
left join pg_class d on a.relation=d.oid
where  a.relation is not null;

granted カラムが「t」となっているプロセスが、ロックを取得しています。「f」となっているのが、ロック待ちとなっているプロセスです。 blocking_pid カラムのプロセスが、ロック待ちを発生させているプロセスとなります。

プロセスで実行されているクエリを取得する

悪さをしているプロセスidまで特定できたので、具体的にどういったクエリが実行されているか確認します。以下のSQLです。SuperUserで実行。

select pid, user_name, starttime, query
from stv_recents
where status='Running' AND pid='xxxx';

公式。

実行中のクエリのプロセス ID を調べる - Amazon Redshift

プロセスを手動で停止する

以下のコマンドで、指定したプロセスを強制終了できます。Superuserで実行。

select pg_terminate_backend(XXXX); 

公式。

PG_TERMINATE_BACKEND - Amazon Redshift