## Lock 정보 확인 쿼리
``` sql
select locktype, relation::regclass, mode, transactionid tid, pid, granted from pg_catalog.pg_locks where not pid=pg_backend_pid();
```
- insert 문을 실행했을 때 결과
| locktype | relation | mode | tid | pid | granted |
| ------------- | -------- | ---------------- | ----- | ----- | ------- |
| relation | 17412 | RowExclusiveLock | NULL | 66376 | TRUE |
| relation | 17406 | RowExclusiveLock | NULL | 66376 | TRUE |
| virtualxid | NULL | ExclusiveLock | NULL | 66376 | TRUE |
| transactionid | NULL | ExclusiveLock | 14144 | 66376 | TRUE |
## Lock 종류
### Table 수준 Lock
| Lock Mode | Access Share | Row Share | Row Exclusive | Share Update Exclusive | Share | Share Row Exclusive | Exclusive | Access Exclusive |
|:--------------------------:|:------------:|:---------:|:-------------:|:----------------------:|:-----:|:-------------------:|:---------:|:----------------:|
| __Access Share__ | | | | | | | | X |
| __Row Share__ | | | | | | | X | X |
| __Row Exclusive__ | | | | | X | X | X | X |
| __Share Update Exclusive__ | | | | X | X | X | X | X |
| __Share__ | | | X | X | | X | X | X |
| __Share Row Exclusive__ | | | X | X | X | X | X | X |
| __Exclusive__ | | X | X | X | X | X | X | X |
| __Access Exclusive__ | X | X | X | X | X | X | X | X |
#### Access Share
- 일반적인 SELECT 쿼리를 쓰면 얻을 수 있다.
- Access Exclusive Lock과 충돌하고 다른 Lock과는 충돌하지 않는다.
#### Row Share
- [[SELECT FOR SHARE]] 쿼리나 [[SELECT FOR UPDATE]] 쿼리를 쓰면 얻을 수 있다.
- Exclusive, Access Exclusive Lock과 충돌한다.
#### Row Exclusive
- INSERT, UPDATE, DELETE 쿼리를 쓰면 얻을 수 있다.
- Share, Share Row Exclusive, Exclusive, Access Exclusive Lock과 충돌한다.
#### Share Update Exclusive
- [[PostgreSQL VACUUM|VACUUM]](full 제외), [[PostgreSQL ANALYZE|ANALYZE]], CREATE INDEX CONCURRENTLY, CREATE STATISTICS, ALTER TABLE VALIDATE, ALTER TABLE을 수행할 때 얻을 수 있다.
- Share Update Exclusive, Share, Share Row Exclusive, Exclusive, Access Exclusive Lock과 충돌한다.
#### Share
- CREATE INDEX(concurrently 없이)를 수행할 때 얻을 수 있다.
- 테이블에서 동시 데이터 변경을 막는다.
- Row Exclusive, Share Update Exclusive, Share Row Exclusive, Exclusive, Access Exclusive Lock과 충돌한다.
#### Share Row Exclusive
- CREATE COLLATION, CREATE TRIGGER를 수행할 때 얻을 수 있다.
- 테이블에서 동시 데이터 변경을 막고, 오직 한 세션만 Share Row Exclusive Lock을 얻을 수 있다.
- Row Exclusive, Share Update Exclusive, Share, Share Row Exclusive, Exclusive, Access Exclusive Lock과 충돌한다.
#### Exclusive
- REFRESH MATERIALIZED VIEW CONCURRENTLY를 수행할 때 얻을 수 있다.
- Access Share를 제외한 모든 Lock에 충돌한다.
#### Access Exclusive
- DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL, REFRESH MATERIALIZED VIEW(concurrently 없이)를 수행할 때 얻을 수 있다.
- LOCK TABLE 명령어로 명시적인 Lock을 걸면 Access Exclusive Lock을 얻는다.
- 모든 Lock에 충돌한다.
### Row 수준 Lock
| Lock Mode | For Key Share | For Share | For No Key Update | For Update |
| --------------------- |:-------------:|:---------:|:-----------------:|:----------:|
| __For Key Share__ | | | | X |
| __For Share__ | | | X | X |
| __For No Key Update__ | | X | X | X |
| __For Update__ | X | X | X | X |
#### For Update
- 대상 row에 SELECT, UPDATE, DELETE를 하면 얻을 수 있다.
- UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR NO KEY UPDATE, SELECT FOR SHARE, SELECT FOR KEY SHARE를 하면 충돌한다.
#### For No Key Update
- For Update와 같지만 SELECT FOR KEY SHARE와 충돌하지 않는다.
- UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR NO KEY UPDATE, SELECT FOR SHARE를 하면 충돌한다.
#### For Share
- For No Key Update와 같지만 ExclusiveLock 대신 SharedLock을 얻는다.
- UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR NO KEY UPDATE를 하면 충돌한다.
#### For Key Share
- For Share와 같지만 For No Key Update를 허용한다.
- UPDATE, DELETE, SELECT FOR UPDATE를 하면 충돌한다.
### Page 수준 Lock
- 공유 버퍼 풀의 테이블 페이지 read/write 접근을 제어한다.
- row을 가져오거나 update한 직후에 해제된다.
- 일반적인 애플리케이션 개발자는 신경 쓰지 않아도 된다.
### Advisory Lock
- 시스템이 락을 강제하는 것이 아니라 애플리케이션에서 락을 걸 수 있는 함수를 제공한다.
- 그래서 advisory(권고)이다.
#### session 수준
- 명시적으로 Lock을 해제하거나 세션이 종료될 때까지 Lock이 유지된다.
#### transaction 수준
- 명시적으로 해제할 수 없고 트랜잭션이 종료될 때 자동으로 해제된다.
#db #postgresql