Lock:advisory - Amazon Aurora

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

Lock:advisory

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

Versi mesin yang relevan

Informasi peristiwa tunggu ini relevan untuk Aurora PostgreSQL versi 9.6 dan yang lebih tinggi.

Konteks

Kunci penasihat PostgreSQL adalah kunci kooperatif tingkat aplikasi yang secara eksplisit dikunci dan dibuka oleh kode aplikasi pengguna. Aplikasi dapat menggunakan kunci penasihat 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 Kunci Penasihat dalam dokumentasi PostgreSQL.

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

Untuk deskripsi fungsi yang digunakan untuk memperoleh (mengunci) dan melepaskan (membuka kunci) kunci penasihat, lihat Fungsi Kunci Penasihat dalam dokumentasi PostgreSQL.

Kunci penasihat diterapkan di atas sistem penguncian PostgreSQL biasa dan terlihat dalam tampilan sistem pg_locks.

Penyebab

Jenis kunci ini secara eksklusif dikendalikan oleh aplikasi yang menggunakannya secara eksplisit. Kunci penasihat 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 Kunci Penasihat 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 berkembang 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

Tinjau penggunaan kunci penasihat oleh aplikasi dan jelaskan secara detail di mana dan kapan dalam alur aplikasi setiap jenis kunci penasihat diperoleh dan dilepaskan.

Ketahui apakah sesi memperoleh terlalu banyak kunci atau sesi yang berjalan lama tidak melepaskan kunci cukup awal, sehingga mengarah ke 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 penasihat muncul dalam pg_stat_activity dengan wait_event_type=Lock dan wait_event=advisory. Anda dapat memperoleh nilai kunci tertentu dengan membuat kueri tampilan sistem pg_locks untuk pid yang sama, dengan mencari locktype=advisory dan granted=f.

Anda kemudian dapat mengidentifikasi sesi pemblokiran dengan membuat kueri pg_locks untuk kunci penasihat 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 penasihat memiliki dua set argumen, baik satu argumen bigint atau dua argumen integer:

  • Untuk fungsi API dengan satu argumen bigint, 32 bit atas masuk dalam pg_locks.classid dan 32 bit bawah masuk 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 formulir API yang digunakan: 1 berarti satu argumen bigint; 2 berarti dua argumen integer.