# 궁금증1 : 포스트그레 디비의 락 관리 방법
# 궁금증2 : select for update문으로 row lock이 걸린다고 알고있는데, 결과가 없는 레코드를 select for update 하면 '테이블락'이 걸린다는 소문 검증
pg_locks 테이블을 통해 락을 관리한다. SELECT * FROM pg_locks 구문을 실행시키면 현재 디비에 걸려있는 LOCK들을 조회할 수 있다.# 예시 데이터
{
"SELECT * FROM pg_locks": [
{
"locktype" : "relation",
"database" : 111111, <- 임의의 숫자로 수정한 것
"relation" : 222222, <- 임의의 숫자로 수정한 것
"page" : null,
"tuple" : null,
"virtualxid" : null,
"transactionid" : null,
"classid" : null,
"objid" : null,
"objsubid" : null,
"virtualtransaction" : "5\/1924",
"pid" : 111, <- 임의의 숫자로 수정한 것
"mode" : "ExclusiveLock",
"granted" : true,
"fastpath" : false,
"waitstart" : null
}
]
}
pg_locks 조회시
relation 의 value -> 어떤 대상에게 락을 걸었는가
mode 의 value -> 어떤 락을 걸었는가
relation 의 value는 pg_class.oid 이므로 해당 테이블 조회하면 어떤 대상에게 락을 걸었는지 확인할 수 있다.
# 예시데이터1 (이 경우에는 테이블 명이 relname에 조회되고 있으므로 테이블 락이라고 볼 수 있다.)
{
"select oid, relname from pg_catalog.pg_class where oid = 222222": [
{
"oid" : 222222,
"relname" : "test_table_name"
}
]
}
SELECT pid, usename, state, query_start, now() - query_start AS runtime, query
FROM pg_stat_activity
WHERE pid = 24620
ORDER BY runtime DESC;
SELECT pid, usename, state, query_start, now() - query_start AS runtime, query
FROM pg_stat_activity
where state = 'idle in transaction'
ORDER BY runtime DESC;
"select oid, relname from pg_catalog.pg_class where oid = 333333": [
{
"oid" : 333333,
"relname" : "test_table_name_pkey"
}
]
}
---
### 테스트
**1. 방법**
- DBeaver에서 sql창 2개 띄워놓고 테스트
- app 2개 띄워두고 한쪽에서 `select for update`로 row 걸고 다른쪽에서 접근테스트
**2. 결론**
> **`select for update`로 row lock을 걸었을 때**
>
1. row lock 범위에 해당하지 않는 다른 row의 배타락을 요청한다
-> 성공
2. row lock 범위에 해당하는 row를 단순 조회한다.
-> 성공
3. row lock 범위에 해당하는 row에 배타락을 요청한다.
-> 대기(앞전 트랜잭션이 종료되면 진행)
> ** 존재하지 않는 row에 대하여 배타락 획득 요청시**
- `pg_locks 테이블`에 Row Shared Lock으로 값이 추가되긴 하지만,
실제로 Lock이 걸리는 부분은 없어보인다.
-> 위 케이스에서 진행된 1,2,3 모두 성공한다.
` 테이블 락, row lock 둘다 x `
---
+++
아래와 같이 트랜잭션을 여닫으며 테스트 진행했다.
```sql
BEGIN WORK;
lock table 테스트 대상 테이블이름 IN EXCLUSIVE MODE;
commit work;