

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Lock:advisory
<a name="wait-event.lockadvisory"></a>

Peristiwa `Lock:advisory` terjadi saat aplikasi PostgreSQL menggunakan kunci untuk mengoordinasi aktivitas di beberapa sesi.

**Topics**
+ [Versi mesin yang relevan](#wait-event.lockadvisory.context.supported)
+ [Konteks](#wait-event.lockadvisory.context)
+ [Penyebab](#wait-event.lockadvisory.causes)
+ [Tindakan](#wait-event.lockadvisory.actions)

## Versi mesin yang relevan
<a name="wait-event.lockadvisory.context.supported"></a>

Informasi peristiwa tunggu ini relevan untuk RDS for PostgreSQL versi 9.6 dan lebih tinggi.

## Konteks
<a name="wait-event.lockadvisory.context"></a>

Kunci advisory PostgreSQL adalah kunci kooperatif tingkat aplikasi yang secara eksplisit dikunci dan dibuka oleh kode aplikasi pengguna. Aplikasi dapat menggunakan kunci advisory PostgreSQL untuk mengoordinasi aktivitas di beberapa sesi. Tidak seperti kunci biasa tingkat objek atau baris, aplikasi memiliki kontrol penuh atas masa pakai kunci. Untuk informasi selengkapnya, lihat [Advisory Locks](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) dalam dokumentasi PostgreSQL.

Kunci advisory dapat dilepaskan sebelum transaksi berakhir atau disimpan oleh sesi di seluruh transaksi. Hal ini tidak berlaku untuk kunci implisit yang diberlakukan sistem, seperti kunci eksklusif akses pada tabel yang diperoleh oleh pernyataan `CREATE INDEX`.

Untuk deskripsi fungsi yang digunakan untuk memperoleh (mengunci) dan melepaskan (membuka kunci) kunci advisory, lihat [Advisory Lock Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) dalam dokumentasi PostgreSQL.

Kunci advisory diimplementasikan di atas sistem penguncian PostgreSQL biasa dan terlihat dalam tampilan sistem `pg_locks`.

## Penyebab
<a name="wait-event.lockadvisory.causes"></a>

Jenis kunci ini secara khusus dikendalikan oleh aplikasi yang secara eksplisit menggunakannya. Kunci advisory yang diperoleh untuk setiap baris sebagai bagian dari kueri dapat menyebabkan lonjakan kunci atau penumpukan jangka panjang.

Efek ini terjadi saat kueri dijalankan dengan cara yang memperoleh kunci pada lebih banyak baris daripada yang ditampilkan oleh kueri. Aplikasi pada akhirnya harus melepaskan setiap kunci, tetapi jika kunci diperoleh pada baris yang tidak ditampilkan, maka aplikasi tidak dapat menemukan semua kunci.

Contoh berikut berasal dari [Advisory Locks](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) dalam dokumentasi PostgreSQL.

```
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100;
```

Dalam contoh ini, klausa `LIMIT` hanya dapat menghentikan output kueri setelah baris dipilih secara internal dan nilai ID-nya dikunci. Hal ini dapat terjadi secara tiba-tiba saat volume data yang bertambah menyebabkan perencana memilih rencana eksekusi lain yang tidak diuji selama pengembangan. Penumpukan dalam kasus ini terjadi karena aplikasi secara eksplisit memanggil `pg_advisory_unlock` untuk setiap nilai ID yang terkunci. Namun, dalam kasus ini, aplikasi tidak dapat menemukan set kunci yang diperoleh pada baris yang tidak ditampilkan. Karena diperoleh pada tingkat sesi, kunci tidak dilepaskan secara otomatis pada akhir transaksi.

Kemungkinan penyebab lain untuk lonjakan upaya kunci yang diblokir adalah konflik yang tidak diinginkan. Dalam konflik ini, bagian aplikasi yang tidak terkait berbagi ruang ID kunci yang sama secara tidak sengaja.

## Tindakan
<a name="wait-event.lockadvisory.actions"></a>

Tinjau penggunaan kunci advisory oleh aplikasi dan cari tahu secara mendetail di mana dan kapan dalam alur aplikasi setiap jenis kunci advisory diperoleh dan dilepaskan.

Ketahui apakah sesi memperoleh terlalu banyak kunci atau sesi yang berjalan lama tidak melepaskan kunci cukup awal, sehingga mengakibatkan penumpukan kunci yang lambat. Anda dapat memperbaiki penumpukan kunci tingkat sesi yang lambat dengan mengakhiri sesi menggunakan `pg_terminate_backend(pid)`. 

Klien yang menunggu kunci advisory muncul dalam `pg_stat_activity` dengan `wait_event_type=Lock` dan `wait_event=advisory`. Anda dapat memperoleh nilai kunci tertentu dengan mengkueri tampilan sistem `pg_locks` untuk `pid` yang sama, dengan mencari `locktype=advisory` dan `granted=f`.

Anda kemudian dapat mengidentifikasi sesi yang memblokir dengan mengkueri `pg_locks` untuk kunci advisory serupa yang memiliki `granted=t`, seperti ditunjukkan dalam contoh berikut.

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

Semua fungsi API kunci advisory memiliki dua set argumen, baik satu argumen `bigint` maupun dua argumen `integer`:
+ Untuk fungsi API dengan satu argumen `bigint`, 32 bit atas berada dalam `pg_locks.classid` dan 32 bit bawah berada dalam `pg_locks.objid`.
+ Untuk fungsi API dengan dua argumen `integer`, argumen pertama adalah `pg_locks.classid` dan argumen kedua adalah `pg_locks.objid`.

Nilai `pg_locks.objsubid` menunjukkan form API yang digunakan: `1` berarti satu argumen `bigint`; `2` berarti dua argumen `integer`.