Lock:Relation - Amazon Aurora

Lock:Relation

Lock:Relation 이벤트는 쿼리가 현재 다른 트랜잭션에 의해 잠긴 테이블 또는 뷰(관계식)에 대한 잠금을 얻기 위해 대기 중일 때 발생합니다.

지원되는 엔진 버전

이 대기 이벤트 정보는 모든 버전의 Aurora PostgreSQL에서 지원됩니다.

컨텍스트

대부분의 PostgreSQL 명령은 암시적으로 잠금을 사용하여 테이블의 데이터에 대한 동시 액세스를 제어합니다. 애플리리케이션 코드에서 LOCK 명령과 함께 이러한 잠금을 명시적으로 사용할 수도 있습니다. 많은 잠금 모드는 서로 호환되지 않으며 동일한 객체에 액세스하려고 할 때 트랜잭션을 차단할 수 있습니다. 이 경우 Aurora PostgreSQL은 Lock:Relation 이벤트를 생성합니다. 다음은 몇 가지 일반적인 예입니다.

  • ACCESS EXCLUSIVE와 같은 독점 잠금은 모든 동시 액세스를 차단할 수 있습니다. 데이터 정의 언어(DDL) 작업(예: DROP TABLE,TRUNCATE,VACUUM FULL, 및CLUSTER)은 명시적으로 ACCESS EXCLUSIVE 잠금을 획득합니다. 또한 ACCESS EXCLUSIVE는 모드를 명시적으로 식별하지 않는 LOCK TABLE 문을 위한 기본 잠금 모드입니다.

  • 데이터 조작 언어(DML) 명령문 UPDATE,DELETE, 및 INSERT와 충돌하는 테이블에 ROW EXCLUSIVE 잠금을 획득하는 CREATE INDEX (without CONCURRENT)를 사용하세요.

테이블 수준 잠금 및 충돌하는 잠금 모드에 대한 자세한 내용은 PostgreSQL 설명서의 명시적 잠금을 참조하세요.

쿼리 및 트랜잭션 차단은 일반적으로 다음 중 한 가지 방법으로 잠금 해제합니다.

  • 쿼리 차단 - 애플리케이션이 쿼리를 취소하거나 사용자가 프로세스를 종료할 수 있습니다. 세션의 명령문 시간 초과 또는 교착 상태 감지 메커니즘으로 인해 엔진이 쿼리를 강제로 종료할 수도 있습니다.

  • 트랜잭션 차단 - 트랜잭션이 ROLLBACK이나 COMMIT 문을 실행할 때 차단을 중지합니다. 롤백은 클라이언트 또는 네트워크 문제로 세션의 연결이 끊어지거나 종료된 경우에도 자동으로 수행됩니다. 세션은 데이터베이스 엔진이 종료될 때, 시스템의 메모리가 부족할 때 종료될 수 있습니다.

대기 증가의 가능한 원인

Lock:Relation 이벤트가 평소보다 더 자주 발생하면 성능 문제를 나타낼 수 있습니다. 일반적인 원인은 다음과 같습니다.

테이블 잠금 충돌로 인한 동시 세션 증가

잠금 모드가 충돌하는 동일한 테이블을 하거나 잠그는 쿼리의 동시 세션 수가 증가할 수 있습니다.

유지 관리 작업

VACUUMANALYZE 같은 상태 유지 관리 작업은 충돌하는 잠금 수를 크게 늘릴 수 있습니다. VACUUM FULL은 하나의 ACCESS EXCLUSIVE 잠금을, ANALYSE는 하나의 SHARE UPDATE EXCLUSIVE 잠금을 획득합니다. 두 가지 유형의 잠금은 모두 Lock:Relation 대기 이벤트를 발생시킬 수 있습니다. 구체화된 뷰 새로 고침과 같은 애플리케이션 데이터 유지 관리 작업은 차단된 질의 및 트랜잭션을 증가시킬 수도 있습니다.

리더 인스턴스 잠금

라이터와 리더가 보유한 관계 잠금 간에 충돌이 있을 수 있습니다. 현재 ACCESS EXCLUSIVE 관계 잠금만 리더 인스턴스에 복제됩니다. 그러나 ACCESS EXCLUSIVE 관계 잠금은 리더가 보유한 모든 ACCESS SHARE 관계 잠금과 충돌합니다. 이로 인해 리더에서 잠금 관계 대기 이벤트가 증가할 수 있습니다.

작업

대기 이벤트의 원인에 따라 다른 작업을 권장합니다.

SQL 문 차단의 영향 감소

SQL 문 차단의 영향을 줄이려면 가능한 경우 애플리케이션 코드를 수정하세요. 다음은 블록을 줄이기 위한 두 가지 일반적인 기술입니다.

  • NOWAIT 옵션 사용 - SELECTLOCK 문 같은 일부 SQL 명령은 이 옵션을 지원합니다. NOWAIT 지시어는 잠금을 즉시 획득할 수 없는 경우 잠금 요청 쿼리를 취소합니다. 이 기술은 차단 세션이 그 뒤에 차단된 세션이 쌓이지 않게 하는 데 도움이 될 수 있습니다.

    예: 트랜잭션 A가 트랜잭션 B가 보유한 잠금을 기다리고 있다고 가정합니다. 이제 B가 트랜잭션 C에 의해 잠긴 테이블에 대한 잠금을 요청하면 트랜잭션 C가 완료될 때까지 트랜잭션 A가 차단될 수 있습니다. 그러나 트랜잭션 B가 NOWAIT를 사용하는 경우 C에서 잠금을 요청하면 빠르게 실패하고 트랜잭션 A가 계속해서 기다릴 필요가 없도록 할 수 있습니다.

  • SET lock_timeout 사용 - SQL 문이 관계식 잠금을 획득하기 위해 대기하는 시간을 제한하는 lock_timeout 값을 설정하세요. 지정된 제한 시간 내에 잠금을 획득하지 않으면 잠금을 요청하는 트랜잭션이 취소됩니다. 세션 수준에서 이 값을 설정합니다.

유지 보수 작업의 영향 최소화

VACUUMANALYZE 같은 유지 관리 작업이 중요합니다. 이러한 유지 관리 작업과 관련된 Lock:Relation 대기 이벤트를 찾을 수 있으므로 끄지 않는 것이 좋습니다. 다음 방법을 사용하면 이러한 작업의 효과를 최소화할 수 있습니다.

  • 사용량이 적은 시간대에 수동으로 유지 관리 작업을 실행합니다.

  • Autovacuum 작업으로 인한 Lock:Relation 대기를 줄이려면 필요한 autovacuum 튜닝을 수행하세요. Autovacuum 튜닝에 대한 자세한 내용은 Amazon RDS 사용 설명서Amazon RDS에서 PostgreSQL Autovacuum 사용을 참조하세요.

리더 잠금 확인

라이터 및 리더의 동시 세션이 서로를 차단하는 잠금을 유지하는 방법을 확인할 수 있습니다. 이를 수행하는 한 가지 방법은 잠금 유형 및 관계를 반환하는 쿼리를 실행하는 것입니다. 테이블에서 두 개의 동시 세션, 즉 라이터 세션(왼쪽 열)과 리더 세션(오른쪽 열)에 대한 쿼리 시퀀스를 찾을 수 있습니다.

재생 프로세스는 리더 쿼리를 취소하기 전에 max_standby_streaming_delay 기간 동안 기다립니다. 예에서 볼 수 있듯이 100ms의 잠금 시간 제한은 기본값 max_standby_streaming_delay인 30초보다 훨씬 낮습니다. 문제가 발생하기 전에 잠금 시간이 초과됩니다.

라이터 세션 리더 세션
export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com psql -h $WRITER psql (15devel, server 10.14) Type "help" for help.
export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com psql -h $READER psql (15devel, server 10.14) Type "help" for help.
작성기 세션은 라이터 인스턴스에서 t1 테이블을 생성합니다. 라이터에 충돌하는 쿼리가 없다고 가정하면 ACCESS EXCLUSIVE 잠금이 라이터에 즉시 획득됩니다.
postgres=> CREATE TABLE t1(b integer); CREATE TABLE
리더 세션은 잠금 시간 초과 간격을 100밀리초로 설정합니다.
postgres=> SET lock_timeout=100; SET
리더 세션이 리더 인스턴스의 t1 테이블에서 데이터를 읽으려고 시도합니다.
postgres=> SELECT * FROM t1; b --- (0 rows)
라이터 세션이 t1을 삭제합니다.
postgres=> BEGIN; BEGIN postgres=> DROP TABLE t1; DROP TABLE postgres=>
쿼리 시간이 초과되고 리더에서 취소됩니다.
postgres=> SELECT * FROM t1; ERROR: canceling statement due to lock timeout LINE 1: SELECT * FROM t1; ^
리더 세션이 pg_lockspg_stat_activity를 쿼리하여 오류의 원인을 확인합니다. 결과는 aurora wal replay 프로세스가 t1 테이블의 ACCESS EXCLUSIVE 잠금을 유지하고 있습니다.
postgres=> SELECT locktype, relation, mode, backend_type postgres-> FROM pg_locks l, pg_stat_activity t1 postgres-> WHERE l.pid=t1.pid AND relation = 't1'::regclass::oid; locktype | relation | mode | backend_type ----------+----------+---------------------+------------------- relation | 68628525 | AccessExclusiveLock | aurora wal replay (1 row)