Kunci CREATE TABLE

19

Di aplikasi lain saya dikejutkan oleh desain yang buruk: beberapa thread menjalankan EnsureDatabaseSchemaExists()metode secara bersamaan, yang pada dasarnya terlihat seperti ini:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'MyTable') AND type = N'U') BEGIN

    CREATE TABLE MyTable ( ... );

END

Namun, bahkan jika dieksekusi dalam transaksi SERIALIZABLE, kode ini tampaknya tidak aman-thread (yaitu kode paralel mencoba membuat tabel beberapa kali). Apakah ada peluang untuk memaksa pernyataan SELECT untuk mendapatkan kunci yang mencegah utas lain untuk melakukan pernyataan SELECT yang sama?

Apakah ada pola yang lebih baik untuk metode multi-threaded-EnsureSchemaExists ()?

DR
sumber

Jawaban:

18

Anda bertaruh terbaik adalah dengan menggunakan transaksi yang mengandung eksplisit dan memperoleh kunci eksklusif khusus untuk melindungi seluruh operasi ( SELECTdan CREATE TABLE) menggunakan sp_getapplock . Objek sistem tidak memenuhi permintaan tingkat isolasi dan menggunakan kunci dengan cara yang sama seperti tabel pengguna, dengan desain.

Kondisi lomba dalam kode asli adalah bahwa beberapa utas dapat menyimpulkan bahwa tabel tidak ada sebelum utas apa pun mencapai sejauh CREATE TABLEpernyataan.

Paul White mengatakan GoFundMonica
sumber
6
+1 pastikan applock membungkus cek SELECT . Kalau tidak, Anda akan memperkenalkan kebuntuan. Idealnya orang akan mendapatkan kunci aplikasi dalam mode S, periksa, upgrade ke X, tapi itu sulit (untuk sedikitnya ...). Opsi teraman adalah memperoleh X, kemudian melakukan seluruh penyebaran skema DB. Ini harus menjadi op yang langka (mis. Saat startup aplikasi) sehingga kunci X seharusnya tidak terlalu penting.
Remus Rusanu
12

Rekomendasi saya adalah melakukan upaya / tangkapan terbaik. Tangani kasus duplikat secara eksplisit, jika perlu, mis. abaikan itu...

Pertanyaan sebenarnya: mengapa DDL berjalan berdasarkan permintaan, dari banyak xacts? Biasanya pemutakhiran dan migrasi adalah masalah serius, ditangani di jendela waktu khusus ... Anda tidak ingin migrasi Anda (kode-pertama?) Tiba-tiba muncul, beberapa langkah pembaruan itu bisa memakan waktu berjam-jam di meja besar (ukuran-of) operasi data ...)

Remus Rusanu
sumber
3
Kode adalah semacam DatabaseLogger yang membuat tabel sesuai permintaan. Tidak ada migrasi, tidak ada bisnis lucu. Namun, Anda sepenuhnya benar. Saya akan memperbaiki kode dengan tepat.
DR
4
Juga pertimbangkan penyebaran / pengaturan yang OK untuk dijalankan pada konteks privilege tinggi (mis. Oleh admin), tetapi operasi normal tidak. Saat ini Anda memerlukan CREATE TABLEhibah untuk operasi normal ...
Remus Rusanu