Topik temu duga representatif

Bagaimanakah Anda Menggunakan OLD dan NEW PostgreSQL 18 dalam RETURNING?

DataSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Anda perlu mengeluarkan peristiwa audit untuk setiap baris yang diubah oleh upsert dan MERGE. Bagaimanakah anda menggunakan RETURNING PostgreSQL 18 dengan OLD dan NEW tanpa mewujudkan perlumbaan bacaan kedua (second read race)?

Masalah dan konteks

PostgreSQL 18 membolehkan RETURNING mendedahkan nilai baris lama dan baharu secara eksplisit untuk INSERT, UPDATE, DELETE, dan MERGE. Hasilnya dihasilkan oleh penyata penukaran data yang sama, yang dapat mengelakkan pertanyaan susulan daripada berlumba dengan penulis lain. Bahagian lama atau baharu boleh menjadi NULL apabila bahagian tersebut tidak wujud untuk sesuatu operasi.

Andaikan peristiwa audit memerlukan nilai tepat yang diubah oleh satu penyata, percubaan semula (retries) mestilah idempoten, dan aplikasi tidak mampu menampung bacaan kedua antara mutasi dan pelepasan audit.

Perkara yang dinilai oleh penemu duga

Penemu duga mencari keatoman pada peringkat penyata, semantik operasi yang betul, dan rancangan untuk sempadan transaksi serta percubaan semula. Jawapan yang kukuh membezakan INSERT, UPDATE, DELETE, ON CONFLICT, dan MERGE, serta menerangkan kedudukan penghantaran audit berbanding commit.

Jawapan biasa memilih (SELECT) baris itu semula selepas penulisan. Jawapan yang kukuh menggunakan RETURNING sebagai output mutasi, mengekalkan identiti operasi, dan mengelakkan penerbitan peristiwa yang kemudiannya diundur (rollback) oleh transaksi.

Soalan untuk dijelaskan terlebih dahulu

  • Adakah peristiwa audit mesti dikeluarkan hanya selepas commit, atau adakah baris outbox mencukupi?
  • Bolehkah satu penyata mengubah banyak baris, dan bagaimanakah ID peristiwa diperuntukkan?
  • Apakah maksud “old” bagi konflik upsert dan untuk setiap tindakan MERGE?
  • Bagaimanakah percubaan semula akan mengelakkan peristiwa audit pendua?
  • Adakah terdapat lajur yang mesti diredaksikan sebelum meninggalkan pangkalan data?

Jika penghantaran hiliran mesti mengikut commit, masukkan baris outbox dalam transaksi yang sama dan terbitkan secara tidak segerak. Jika audit hanya untuk laporan SQL dalaman, RETURNING boleh digunakan secara terus oleh pemanggil.

Jawapan 30 saat

“Saya akan membuat penyata mutasi mengembalikan operasi eksplisit, nilai lama, nilai baharu, dan kunci peristiwa yang stabil. Untuk penulisan berbilang baris, saya akan memasukkan hasil tersebut ke dalam outbox dalam transaksi yang sama, kemudian menerbitkannya selepas commit. Saya akan menguji bahagian NULL untuk insert dan delete, mentakrifkan semantik upsert dan MERGE, meredaksikan lajur sensitif, dan menjadikan percubaan semula idempoten menggunakan kunci peristiwa.”

Reka bentuk langkah demi langkah

  1. Takrifkan kontrak peristiwa. Sertakan identiti jadual, kunci utama, operasi, unjuran lama, unjuran baharu, ID transaksi atau permintaan, dan kunci keidempoteman.
  2. Gunakan alias eksplisit. Tulis RETURNING WITH (OLD AS old_row, NEW AS new_row) atau sintaks terdokumen yang setara dan bukannya bergantung pada RETURNING *.
  3. Kendalikan semantik operasi. Insert biasanya tidak mempunyai baris lama; delete biasanya tidak mempunyai baris baharu. Upsert dan MERGE memerlukan nilai operasi khusus untuk setiap cabang.
  4. Kekalkan secara atomik. Masukkan rekod yang dikembalikan ke dalam outbox dalam transaksi yang sama. Bacaan berasingan atau penerbitan luaran sebelum commit boleh melihat keadaan yang kemudiannya diundur (rollback).
  5. Lindungi data dan percubaan semula. Redaksikan medan, cincang nilai sensitif jika sesuai, dan kuat kuasakan kunci peristiwa yang unik supaya penyata yang dicuba semula tidak menduplikasi penghantaran.
  6. Sahkan keserentakan. Jalankan penulis serentak, konflik, pengunduran (rollbacks), penyata berbilang baris, dan cabang MERGE separa. Bandingkan baris audit dengan keadaan jadual yang telah di-commit.

Alternatif termasuk pencetus (triggers) untuk penguatkuasaan berpusat, penyahkodan logik untuk penangkapan seluruh pangkalan data, atau peristiwa aplikasi untuk semantik domain. RETURNING adalah paling kukuh apabila mutasi sudah memiliki perubahan peringkat baris yang tepat.

Contoh jawapan

“Kemas kini aplikasi mengembalikan operasi eksplisit, kunci utama, unjuran lama, unjuran baharu, dan kunci peristiwa. Untuk konflik upsert, saya melabelkan hasilnya sebagai update; untuk MERGE, setiap cabang membekalkan operasinya sendiri. Transaksi memasukkan setiap baris yang dikembalikan ke dalam outbox dan melakukan commit sekali. Seorang pekerja menerbitkan selepas commit dengan kunci peristiwa yang unik dan mencuba semula dengan selamat. Delete mempunyai unjuran baharu yang null, insert mempunyai unjuran lama yang null, dan lajur sensitif dialih keluar sebelum peristiwa meninggalkan pangkalan data.”

Kesilapan lazim

  • Kesilapan: Menyoal semula selepas mutasi → Sebab ia gagal: penulis lain boleh mengubah baris tersebut → Penyelesaian: gunakan RETURNING daripada penyata yang sama.
  • Kesilapan: Menerbitkan sebelum commit → Sebab ia gagal: peristiwa audit boleh menerangkan data yang diundur (rollback) → Penyelesaian: gunakan transactional outbox.
  • Kesilapan: Memperlakukan setiap upsert sebagai insert → Sebab ia gagal: kemas kini konflik memerlukan semantik yang berbeza → Penyelesaian: keluarkan operasi eksplisit.
  • Kesilapan: Mengembalikan semua lajur secara membuta tuli → Sebab ia gagal: rahsia atau data peribadi bocor → Penyelesaian: gunakan unjuran senarai dibenarkan (allow-list) dan redaksi.

Soalan susulan dan jawapan

Apakah yang terkandung dalam OLD untuk INSERT?

Biasanya tiada baris terdahulu yang wujud, jadi bahagian lama adalah NULL. Kontrak peristiwa harus memodelkan ketiadaan tersebut daripada mereka-reka baris lalai.

Bagaimanakah anda menangkap MERGE berbilang baris?

Gunakan satu hasil RETURNING bagi setiap baris yang terjejas, sertakan operasi cabang, dan masukkan setiap peristiwa ke dalam transaksi outbox yang sama.

Bagaimana jika sisipan outbox gagal?

Transaksi tersebut harus gagal dan mengundurkan (rollback) mutasi. Jangan akui (acknowledge) penulisan perniagaan sambil menggugurkan rekod auditnya secara senyap.

Bilakah anda lebih memilih penyahkodan logik?

Gunakan penyahkodan logik untuk penangkapan perubahan luas di seluruh pangkalan data atau sistem yang tidak boleh mengubah suai penyata. Utamakan RETURNING apabila aplikasi memerlukan unjuran yang peka terhadap domain dan semantik setiap penyata yang tepat.

Sumber awam

Soalan berkaitan