Prompt dan konteks
node:sqlite dalam Node.js 24 mendedahkan API segerak. DatabaseSync mewakili satu sambungan SQLite; createSession() menjejaki perubahan selepas sesi bermula; session.changeset() mengembalikan changeset binari; dan sasaran boleh memanggil applyChangeset() dengan pengendali konflik yang mengabaikan (omit), menggantikan (replace), atau membatalkan (abort). Reka bentuk protokol penyegerakan bertambah antara klien luar talian dan pelayan.
Isu utamanya adalah penyebaran perubahan pangkalan data yang selamat: kunci utama, pemeriksaan nilai lama, dasar konflik, kedap ganda (idempotency), sempadan transaksi, dan kebenaran. Changeset bukanlah SQL yang boleh dilaksanakan dan bukan penggabungan silang pangkalan data secara automatik.
Perkara yang diuji oleh penemu duga
Jawapan yang kukuh memisahkan penjanaan sumber, penghantaran yang boleh dipercayai, penggunaan sasaran atomik, dan keputusan konflik perniagaan. Jangkakan soalan mengenai jangka hayat Session, changeset berbanding patchset, SQLITE_CHANGESET_DATA dan jenis konflik yang berkaitan, penggunaan pendua, evolusi skema, dan cara kerja DatabaseSync segerak mempengaruhi gelung peristiwa (event loop) Node.js.
Pendekatan “Siri dan tulis ganti” akan kehilangan kemas kini sasaran yang bebas. Sentiasa mengembalikan SQLITE_CHANGESET_REPLACE secara senyap menulis ganti data perniagaan dan tidak menyediakan hujah ketepatan.
Soalan untuk dijelaskan terlebih dahulu
Topologi dan autoriti
Tentukan sama ada penyegerakan adalah satu arah, dua hala, atau pengagregatan berbilang klien, dan salinan mana yang berwibawa bagi setiap entiti. Jika kedua-dua pihak mengedit baris yang sama, gunakan versi, ID peranti, atau peristiwa perniagaan untuk menimbang tara; panggilan balik lalai SQLite bukanlah peraturan perniagaan.
Kitaran hayat versi dan skema
Sahkan bahawa sumber dan sasaran berkongsi skema, kunci utama, dan jenis lajur yang sama. Changeset bergantung pada struktur jadual. Migrasi mesti selesai dan membawa versi protokol sebelum changeset lama dimainkan semula.
Kependaman dan sempadan keselamatan
Jelaskan saiz muatan (payload), tetingkap percubaan semula, tempoh luar talian, dan medan sensitif. Muatan binari memerlukan integriti, pengesahan, perlindungan main semula (replay protection), dan penyulitan; ia bukanlah SQL yang dipercayai.
Jawapan 30 saat
“Saya memperuntukkan ID dan kursor versi sumber untuk setiap kelompok (batch). Sumber mencipta Session, melakukan komit transaksi tempatan, dan mengeksport changeset. Pelayan mengesahkan skema, tandatangan, susunan, dan kedap ganda, kemudian memanggil applyChangeset di dalam transaksi sasaran. Pengendali konflik membatalkan (abort) secara lalai dan merekodkan baris, lajur, serta sebab; abaikan atau ganti hanya dibenarkan melalui dasar perniagaan yang jelas. Kelompok yang berjaya memajukan keadaan tahan lama, kegagalan dicuba semula dengan bounded backoff, dan kelompok pendua mengembalikan hasil terdahulu mereka. Kerja SQLite segerak yang besar dijalankan di sebalik worker atau giliran supaya ia tidak menyekat gelung peristiwa Node.”
Penyelesaian langkah demi langkah
Langkah 1: Cipta kelompok yang boleh dijejaki
Selepas mencipta Session, sertakan satu skop transaksi tempatan yang jelas dalam satu kelompok. Rekodkan batchId, peranti sumber, kursor permulaan, versi skema, cincangan (hash) changeset, dan masa penciptaan. Eksport Uint8Array daripada session.changeset(), kemudian tutup atau guna semula Session supaya sejarah tanpa had tidak terkumpul.
Langkah 2: Pilih changeset atau patchset
Changeset merangkumi maklumat nilai lama yang berguna untuk memeriksa sama ada baris sasaran masih sepadan dengan jangkaan. Patchset lebih kecil tetapi mendedahkan kurang konteks nilai lama. Pilih berdasarkan keperluan lebar jalur dan audit; saiz muatan sahaja bukanlah sebab yang mencukupi untuk kehilangan diagnostik.
Langkah 3: Sahkan dan hantar secara kedap ganda
Gunakan TLS, identiti peranti, dan tandatangan muatan. Sahkan saiz, cincangan, versi skema, dan asal usul. Simpan rekod unik yang dikuncikan oleh batchId dan kursor sumber; pendua kelompok yang telah digunakan mengembalikan hasil yang direkodkan. Gunakan kelompok seterusnya mengikut urutan kursor, meletakkan kelompok yang hilang dalam giliran menunggu dan bukannya melangkaunya.
Langkah 4: Gunakan dalam transaksi dan kelaskan konflik
Buka transaksi sasaran dan panggil applyChangeset. Pengendali konflik mengumpul jadual, kunci utama, jenis konflik, dan nilai sasaran dalam penimbal audit. Kembalikan SQLITE_CHANGESET_ABORT secara lalai supaya kelompok itu berundur balik (rollback) secara atomik. Hanya medan yang diluluskan dasar boleh mengembalikan OMIT atau REPLACE, dan keputusan itu perlu direkodkan dalam log yang boleh dimainkan semula.
Langkah 5: Tentukan penggabungan perniagaan
Data yang boleh digabungkan pada peringkat medan boleh menggunakan cap masa, versi monotonik, atau kesatuan set. Wang, inventori, dan kebenaran tidak selamat untuk penggabungan buta; hantarkannya kepada giliran manusia atau peristiwa pampasan. Jangan ubah changeset asal selepas keputusan dibuat. Jana kelompok anak yang mengandungi kelompok induk dan sebab keputusan untuk memelihara rantaian audit.
Langkah 6: Kendalikan jenis data dan ketepatan integer
Node.js dan SQLite menyokong set jenis data yang berbeza. Jika INTEGER SQLite melebihi julat integer selamat JavaScript dan readBigInts dilumpuhkan, membacanya boleh mencetuskan ERR_OUT_OF_RANGE. Piawaikan kepada BigInt, rentetan, atau julat yang jelas. Gunakan Uint8Array untuk nilai BLOB dan tolak objek sebarangan.
Langkah 7: Kawal kos segerak
Panggilan DatabaseSync dilaksanakan secara segerak. Transaksi yang panjang, changeset yang besar, atau panggilan applyChangeset yang kerap boleh menyekat gelung peristiwa. Alihkan penyegerakan kepada worker, proses berasingan, atau giliran terkawal; hadkan muatan dan baris bagi setiap kelompok; pantau tempoh penggunaan, konflik, pengunduran balik, dan usia giliran.
Contoh jawapan berkualiti tinggi
Saya menganggap setiap kelompok penyegerakan sebagai peristiwa yang tidak boleh diubah (immutable). Peranti mencipta ID, kursor, versi skema, dan cincangan; Session hanya meliputi transaksi tempatan yang telah dikomit; dan changeset bergerak melalui saluran yang disahkan dan dilindungi main semula. Pelayan mengesahkan struktur dan susunan, menyahduplikasi mengikut ID kelompok, dan memanggil applyChangeset dalam transaksi SQLite sasaran.
Panggilan balik konflik membatalkan secara lalai, mengundur balik secara atomik dan merekodkan kunci utama, jenis konflik, serta nilai sasaran. Inventori, wang, dan kebenaran dihantar ke penggabungan perniagaan atau pampasan dan bukannya penggantian generik; hanya medan yang selamat secara jelas boleh diabaikan atau diganti. Keadaan kelompok tahan lama memajukan kursor hanya selepas komit. Disebabkan DatabaseSync menyekat secara segerak, saya menjalankan kelompok besar dalam worker dan menguji penghantaran pendua, kelompok yang hilang, migrasi skema, limpahan integer, dan pemulihan ranap proses.
Kesilapan lazim
- Kesilapan: Menulis ganti pangkalan data sasaran pada setiap penyegerakan. → Sebab ia gagal: Kemas kini sasaran bebas hilang. → Penyelesaian: Hantar changeset, bandingkan nilai lama, dan rekodkan keputusan.
- Kesilapan: Mengembalikan
REPLACEuntuk setiap konflik. → Sebab ia gagal: Data perniagaan ditulis ganti secara senyap. → Penyelesaian: Batalkan (abort) secara lalai dan benarkan penggantian bagi setiap medan dan tak varian. - Kesilapan: Menjana kelompok baharu bagi setiap percubaan semula tanpa kunci kedap ganda. → Sebab ia gagal: Penggunaan pendua atau lompatan kursor mencipta kesan sampingan yang berulang. → Penyelesaian: Nyahduplikasi dengan ID kelompok, kursor sumber, dan keadaan aplikasi.
- Kesilapan: Menggunakan changeset yang besar pada gelung peristiwa utama. → Sebab ia gagal: Kerja
DatabaseSyncsegerak menyekat HTTP dan kerja berjadual. → Penyelesaian: Asingkannya dalam worker atau giliran dan hadkan saiz kelompok.
Soalan susulan dan jawapan
Susulan 1: Bilakah anda akan menggunakan patchset?
Gunakan patchset apabila lebar jalur terhad dan sasaran mempunyai konteks yang mencukupi, dengan keperluan audit konflik yang sederhana. Gunakan changeset apabila nilai lama diperlukan untuk menerangkan konflik atau melaksanakan penggabungan yang boleh diaudit, dengan menerima saiz muatan yang lebih besar.
Susulan 2: Bagaimana jika skema sasaran kehilangan lajur?
Tolak kelompok dengan ralat keserasian; jangan biarkan aplikasi meneka pemetaan. Jalankan migrasi sasaran, sahkan versi skema dan kunci utama, kemudian mainkan semula. Jika berbilang versi mesti wujud bersama, tukar mengikut versi protokol sambil mengekalkan muatan asal.
Susulan 3: Bagaimanakah anda menghalang kesan sampingan dalam panggilan balik konflik?
Panggilan balik hanya mengumpul data konflik berstruktur dan mengembalikan keputusan malar. Ia tidak memanggil perkhidmatan luar atau mengubah jadual lain. Tulis rekod audit atau pemberitahuan selepas komit supaya pengunduran balik tidak meninggalkan keadaan luaran yang tidak konsisten.
Susulan 4: Mengapa tidak menghantar SQL secara terus?
SQL tidak mempunyai nilai lama sumber, konteks skema, dan sempadan kelompok. Percubaan semula tidak dapat menentukan dengan pasti sama ada ia telah digunakan, dan pernyataan yang tidak dibenarkan mungkin sampai ke sasaran. Changeset yang dijana SQLite boleh memproses setiap konflik pada sasaran, menjadikannya primitif penyegerakan terkawal yang lebih baik.
Susulan 5: Bagaimanakah anda mengesahkan pariti protokol integer dan BLOB?
Cipta lekapan (fixtures) rentas bahasa untuk integer selamat terbesar, integer di luar julat, nombor negatif, NULL, teks UTF-8, dan muatan binari. Rekodkan jenis SQLite, pilihan baca/tulis Node, dan perwakilan bersiri bagi setiap satu, kemudian sahkan bait dan nilai sepadan sebelum dan selepas dimainkan semula.