Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Jika Anda menggunakan tampilan terindeks dan MERGE, harap baca ini!

Rekan MVP Jamie Thomson baru-baru ini menunjukkan bahwa ada bug "hasil yang salah" di SQL Server yang dapat muncul dengan sendirinya jika kondisi berikut ini benar:

  • Anda memiliki tampilan terindeks yang menggabungkan setidaknya dua tabel;
  • tabel tersebut dibatasi di kedua arah oleh kunci asing satu kolom;
  • Anda melakukan pembaruan pada tabel dasar menggunakan MERGE yang mencakup UPDATE dan (DELETE atau INSERT ) tindakan; dan,
  • Anda kemudian mengeluarkan kueri yang mereferensikan indeks pada tampilan (sengaja atau tidak).

Sayangnya, artikel Basis Pengetahuan yang menjelaskan masalah (KB #2756471) cukup detail. Mereka tidak memberitahu Anda bagaimana mereproduksi masalah, atau bahkan apa, khususnya, Anda harus mencari untuk melihat apakah ini mempengaruhi Anda; dan mereka bahkan tidak menyebutkan MERGE (yang sebenarnya adalah inti masalahnya, bukan NOEXPAND , dan bukan pembaruan sederhana). Ada beberapa detail tambahan di item Connect yang membawa perbaikan; semoga artikel KB akan diperbarui dengan lebih detail sebelum lama.

Sementara itu, hasil yang mungkin Anda lihat adalah data yang salah – atau lebih baik lagi, data basi :Kueri mungkin menunjukkan versi lama dari baris yang diperbarui! Saya menghabiskan beberapa menit mencoba untuk mereproduksi skenario ini di AdventureWorks, dan gagal total. Untungnya, Paul White (blog | @SQL_Kiwi) menulis postingan luar biasa yang menjelaskan skenario dan menampilkan repro lengkap dari masalah tersebut.

Saya rasa saya tidak bisa menekankan betapa seriusnya ini.

Tentunya jutaan pelanggan menggunakan tampilan yang diindeks, banyak dari mereka telah memigrasikan kode DML mereka untuk menggunakan MERGE , dan sebagian besar ada di Edisi Perusahaan (atau tidak tetapi menggunakan NOEXPAND petunjuk atau merujuk indeks secara langsung). Paul dengan cepat menunjukkan bahwa NOEXPAND tidak diperlukan untuk mereproduksi masalah di Edisi Perusahaan, dan juga menemukan banyak detail lain yang diperlukan untuk mereproduksi bug.

Postingan ini tidak dimaksudkan untuk mencuri guntur dari postingan Jamie atau Paul; hanya upaya untuk menegaskan kembali keprihatinan dan untuk meningkatkan kesadaran akan masalah ini. Jika Anda terbiasa mengabaikan Pembaruan Kumulatif, memilih untuk menunggu Paket Layanan, dan ada kemungkinan masalah ini dapat memengaruhi Anda saat ini, Anda berhutang pada diri Anda sendiri, belum lagi pemangku kepentingan dan pelanggan Anda, untuk mengambil masalah ini dengan serius.

Jadi apa yang harus kamu lakukan?

Nah, apa yang Anda lakukan selanjutnya tergantung pada versi dan edisi SQL Server yang Anda jalankan, dan apakah bug tersebut benar-benar memengaruhi Anda (atau bisa).

    SQL Server 2008 SP3
    SQL Server 2008 R2 SP1/SP2
    SQL Server 2012 RTM/SP1

    Opsi Anda jika Anda menggunakan salah satu dari build ini:

    1. Anda harus memperbarui ke Pembaruan Kumulatif terbaru untuk cabang Anda:
      Cabang Tetap di CU Bangun Build minimum diperlukan
      untuk menerapkan pembaruan

      Artikel KB
      (Unduh)
      Paket Layanan 3 2008 CU #8 10.00.5828 10.00.5500 KB #2771833
      Paket Layanan 1 R2 2008 CU #10 10.50.2868 10.50.2500 KB #2783135
      Paket Layanan 2 R2 2008 CU #4 10.50.4270 10.00.4000 KB #2777358
      RTM 2012 CU #5 11.00.2395 11.00.2100 KB #2777772
      Paket Layanan 1 2012 CU #2 11.00.3339 11.00.3000 KB #2790947

      Tabel 1 :Build yang berisi perbaikan

    2. Jika Anda tidak menerapkan perbaikan, maka Anda perlu menguji semua referensi ke tampilan Anda untuk memvalidasi bahwa mereka mengembalikan hasil yang benar dalam semua kasus – termasuk setelah Anda memperbarui tabel dasar menggunakan MERGE . Jika tidak (atau Anda menduga bahwa mereka mungkin akan terpengaruh nanti), maka Anda harus membangun kembali indeks berkerumun pada semua tampilan yang terpengaruh (atau memperbaiki tampilan yang diindeks menggunakan DBCC CHECKTABLE , seperti yang dijelaskan Paul dalam postingannya), dan berhenti menggunakan MERGE terhadap tabel ini sampai Anda menerapkan perbaikan. Jika Anda terus menggunakan MERGE terhadap tabel dasar, bersiaplah untuk terus memperbaiki tampilan untuk menghindari masalah.
    3. Perbaikan yang lebih cepat adalah mencegah tampilan terindeks yang rusak agar tidak digunakan sama sekali, dengan menggunakan salah satu metode berikut yang diperlukan:
      • terapkan petunjuk kueri OPTION (EXPAND VIEWS) untuk semua pertanyaan yang relevan;
      • hapus semua referensi eksplisit ke indeks pada tampilan;
      • di Standar atau edisi lain di mana tampilan yang diindeks tidak dicocokkan secara otomatis, hapus semua contoh NOEXPAND .

      Tapi ini, tentu saja, sebagian besar akan mengalahkan tujuan tampilan yang diindeks – mungkin juga menjatuhkan indeks. Yang mengatakan, biasanya lebih baik untuk mendapatkan hasil yang benar secara perlahan, daripada mendapatkan hasil yang salah dengan cepat; jadi mungkin tidak apa-apa.

    SQL Server 2008 RTM/SP1/SP2
    SQL Server 2008 R2 RTM

    Sayangnya, Anda menggunakan build yang tidak lagi mendukung mainstream, dan kecil kemungkinan masalah ini akan diperbaiki untuk Anda (kecuali jika Anda menggunakan dukungan yang diperluas dan Anda membuat banyak gangguan). Jadi opsi Anda terbatas di sini – pindah ke cabang yang didukung sesuai tabel di atas, dan terapkan Pembaruan Kumulatif, atau pilih salah satu opsi lain yang disebutkan sebelumnya.

    SQL Server 2000
    SQL Server 2005

    Kabar buruknya adalah Anda juga menggunakan build yang tidak lagi didukung. Kabar baiknya adalah bahwa dalam kasus khusus ini tidak masalah – Anda tidak dapat menggunakan MERGE lagi pula, jadi bug ini tidak dapat memengaruhi Anda.

Masalah MERGE lainnya

Sayangnya, ini jauh dari bug pertama yang kami lihat dengan MERGE , dan kemungkinan itu bukan yang terakhir. Berikut adalah pilihan cepat dari selusin MERGE bug yang masih ditandai sebagai aktif di Connect:

  • #773895 :MERGE Salah Melaporkan Pelanggaran Kunci Unik
  • #766165 :MERGE mengevaluasi indeks yang difilter per baris, bukan setelah operasi, yang menyebabkan pelanggaran indeks yang difilter
  • #723696 :Penggabungan dasar yang menyebabkan kebuntuan
  • #713699 :Pemeriksaan pernyataan sistem gagal ("cxrowset.cpp":1528)
  • #699055 :Gabungkan paket kueri memungkinkan FK dan PERIKSA pelanggaran batasan
  • #685800 :Parameterisasi DELETE dan MERGE Izinkan Pelanggaran Batasan Kunci Asing
  • #654746 :penggabungan di SQL2008 SP2 masih mengalami "Mencoba menetapkan nilai kolom yang tidak dapat NULL ke NULL"
  • #635778 :NOT MATCHED dan MATCHED bagian dari pernyataan SQL MERGE tidak dioptimalkan
  • #633132 :PENGGABUNGAN DENGAN SUMBER YANG DIFILTER tidak berfungsi dengan baik
  • #596086 :MERGE statement bug saat INSERT/DELETE menggunakan dan memfilter indeks
  • #583719 :Pernyataan MERGE memperlakukan kolom terhitung yang tidak dapat dibatalkan secara salah dalam beberapa skenario
  • #539084 :MERGE Stmt :Kondisi pencarian pada kolom non-kunci dan ORDER BY dalam tabel turunan sumber memecah MERGE sepenuhnya

Sekarang, mungkin beberapa bug ini sebenarnya telah diperbaiki, tetapi statusnya salah karena loop kembali ke Connect belum ditutup. Bahkan jika itu masalahnya, itu tidak benar untuk mereka semua (dan berpotensi untuk orang lain yang tidak saya temukan).

Selain itu, telah ditunjukkan oleh Dan Guzman bahwa MERGE tidak kebal dari kondisi balapan dan masalah konkurensi lainnya. Solusinya adalah dengan menggunakan HOLDLOCK (atau tingkat isolasi yang lebih tinggi); namun, adalah kesalahpahaman umum bahwa MERGE sepenuhnya atom dan tidak rentan terhadap masalah ini sama sekali. Oleh karena itu saya akan bertanya-tanya:berapa banyak MERGE pernyataan di luar sana termasuk HOLDLOCK (atau sedang dieksekusi di bawah SERIALIZABLE )? Berapa banyak yang telah diuji secara menyeluruh untuk masalah yang berkaitan dengan konkurensi?

Kesimpulan

Secara pribadi, saya pikir sintaksnya bagus (walaupun menakutkan untuk dipelajari), tetapi setiap kali masalah muncul, itu mengikis kepercayaan saya pada kepraktisan mengganti DML yang ada dengan konstruksi baru.

Dengan mengingat hal itu, bukan menjadi Chicken Little, tetapi saya tidak akan merasa nyaman merekomendasikan siapa pun untuk menggunakan MERGE kecuali mereka menerapkan pengujian yang sangat komprehensif. Beberapa masalah ini juga hadir dengan UPSERT standar metodologi, tetapi masalahnya lebih jelas di sana. MERGE , hanya melalui sifat satu-pernyataannya, membuat Anda ingin percaya pada sihir. Mungkin suatu hari nanti itu akan berhasil, tetapi sekarang saya tahu itu tidak akan dapat melihat seseorang menjadi dua tanpa bantuan yang serius.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana Rencana Paralel Memulai – Bagian 2

  2. Bagaimana cara membuat database di SQL?

  3. Bagaimana Mendesain Sistem yang Siap-Lokalisasi

  4. Apa itu Percona DB

  5. SQL ORDER BY:5 Tindakan dan Larangan untuk Mengurutkan Data Seperti Seorang Profesional