Mesin virtual ini meng-host database SharePoint 2007 (SP). Kami telah mengalami banyak deadlock SELECT / INSERT terhadap satu tabel yang banyak digunakan dalam basis data konten SP. Saya telah mempersempit sumber daya yang terlibat, kedua proses ini membutuhkan kunci pada indeks non-cluster.
INSERT memerlukan kunci IX pada sumber daya SELECT dan SELECT membutuhkan kunci S pada sumber daya INSERT. Grafik kebuntuan menggambarkan dan tiga sumber, 1.) dua dari SELECT (utas paralel produsen / konsumen), dan 2.) INSERT.
Saya telah melampirkan grafik kebuntuan untuk ulasan Anda. Karena ini adalah struktur kode dan tabel Microsoft, kami tidak dapat melakukan perubahan apa pun.
Namun, saya telah membaca, di situs MSFT SP, bahwa mereka merekomendasikan pengaturan opsi konfigurasi level Instance MAXDOP ke 1. Karena instance ini dibagikan di antara banyak database / aplikasi lain, pengaturan ini tidak dapat dinonaktifkan.
Oleh karena itu, saya memutuskan untuk mencoba dan mencegah pernyataan SELECT ini berjalan paralel. Saya tahu ini bukan solusi tetapi lebih merupakan modifikasi sementara untuk membantu mengatasi masalah. Oleh karena itu, saya meningkatkan "Ambang Biaya untuk Paralelisme" dari standar kami 25 menjadi 40 saat melakukannya, meskipun beban kerja tidak berubah (SELECT / INSERT sering terjadi) deadlock telah menghilang. Pertanyaan saya adalah mengapa?
SPID 356 INSERT memiliki kunci IX pada halaman milik indeks non-clustered
SPID 690 SELECT ID Eksekusi 0 memiliki kunci S pada halaman milik indeks non clustered yang sama
Sekarang
SPID 356 menginginkan kunci IX pada sumber daya SPID 690 tetapi tidak bisa mendapatkannya karena SPID 356 diblokir oleh SPID 690 ID Eksekusi 0 kunci S
SPID 690 ID Eksekusi 1 menginginkan kunci S pada sumber daya SPID 356 tetapi tidak dapat memperolehnya karena SPID 690 ID Eksekusi 1 diblokir oleh SPID 356 dan sekarang kita memiliki jalan buntu.
Rencana Eksekusi dapat ditemukan di SkyDrive saya
Detail Kebuntuan Lengkap dapat ditemukan di sini
Jika seseorang dapat membantu saya memahami mengapa saya sangat menghargainya.
EventReceivers Table.
Id uniqueidentifier no 16
Nama nvarchar no 512
SiteId uniqueidentifier no 16
WebId uniqueidentifier no 16
HostId uniqueidentifier no 16
HostType int no 4
ItemId int no 4
NamaDn no nvarchar no 512
LeafName nvarchar no 256
Tipe int no 4
SequenceNomor int no 4
Assembly nvarchar no 512
Class nvarchar no 512
Data nvarchar no 512
Filter nvarchar no 512
SourceId tContentTypeId no 512
SourceType int no 4
Kredensial int no 4
ContextType varbinary no 16
ContextEventType varbinary no 16
ContextId varbinary no 16
ContextObjectId varbinary no 16
ContextCollectionId varbinary no 16
nama_index index_description index_keys
EventReceivers_ByContextCollectionId nonclustered terletak di PRIMARY SiteID, ContextCollectionId
EventReceivers_ByContextObjectId nonclustered terletak di PRIMARY SiteID, ContextObjectId
EventReceivers_ById nonclustered, unik terletak di PRIMARY SiteID, Id
EventReceivers_ByTarget berkerumun, unik terletak di PRIMARY SiteID, WebId, hostid, HOSTTYPE, Jenis, ContextCollectionId, ContextObjectId, ContextId, ContextType, ContextEventType, SequenceNumber, Assembly, Class
EventReceivers_IdUnique, kunci unik, tidak bercacah, unik, terletak di PRIMARY Id
sumber
proc_InsertEventReceiver
danproc_InsertContextEventReceiver
melakukan itu kita tidak dapat melihat di XDL itu? Juga untuk mengurangi paralelisme mengapa tidak memengaruhi pernyataan ini secara langsung (menggunakan MAXDOP 1) alih-alih menggunakan pengaturan di seluruh server?Jawaban:
Di wajah itu, ini tampak seperti jalan buntu pencarian klasik . Bahan-bahan penting untuk pola kebuntuan ini adalah:
SELECT
query yang menggunakan indeks nonclustered non-covering dengan Lookup KeyINSERT
query yang memodifikasi indeks berkerumun dan kemudian indeks nonclusteredThe
SELECT
mengakses indeks nonclustered pertama, maka indeks berkerumun. TheINSERT
akses indeks berkerumun pertama, kemudian indeks nonclustered. Mengakses sumber daya yang sama dalam urutan berbeda untuk mendapatkan kunci yang tidak kompatibel adalah cara yang bagus untuk 'mencapai' jalan buntu tentu saja.Dalam hal ini,
SELECT
kueri adalah:... dan
INSERT
kueri adalah:Perhatikan pemeliharaan indeks non-clustered yang disorot hijau.
Kita perlu melihat versi serial dari
SELECT
rencana jika itu sangat berbeda dari versi paralel, tetapi seperti yang dicatat oleh Jonathan Kehayias dalam panduannya untuk Menangani Deadlock , pola kebuntuan khusus ini sangat sensitif terhadap waktu dan detail implementasi pelaksanaan eksekusi kueri internal. Kebuntuan jenis ini sering datang dan pergi tanpa alasan eksternal yang jelas.Mengingat akses ke sistem yang bersangkutan, dan izin yang sesuai, saya yakin kita akhirnya bisa mengetahui persis mengapa kebuntuan terjadi dengan rencana paralel tetapi tidak serial (dengan asumsi bentuk umum yang sama). Jalur-jalur penyelidikan potensial termasuk memeriksa loop tersarang yang dioptimalkan dan / atau pengambilan awal - yang keduanya secara internal dapat meningkatkan tingkat isolasi hingga
REPEATABLE READ
selama pernyataan. Mungkin juga beberapa fitur penugasan rentang indeks paralel berkontribusi terhadap masalah ini. Jika paket serial tersedia, saya mungkin meluangkan waktu untuk melihat detail lebih lanjut, karena berpotensi menarik.Solusi yang biasa untuk jenis deadlocking ini adalah membuat penutup indeks, meskipun jumlah kolom dalam kasus ini mungkin membuat itu tidak praktis (dan selain itu, kami tidak seharusnya mengacaukan hal-hal seperti itu di SharePoint, saya diberitahu). Pada akhirnya, rekomendasi untuk paket serial saja ketika menggunakan SharePoint ada karena suatu alasan (meskipun tidak selalu bagus, ketika sudah sampai pada itu). Jika perubahan ambang biaya untuk paralelisme memperbaiki masalah untuk saat ini, ini bagus. Jangka panjang, saya mungkin akan mencari untuk memisahkan beban kerja, mungkin menggunakan Resource Governor sehingga kueri internal SharePoint mendapatkan
MAXDOP 1
perilaku yang diinginkan dan aplikasi lain dapat menggunakan paralelisme.Pertanyaan tentang pertukaran yang muncul dalam jejak kebuntuan tampaknya menjadi masalah bagi saya; hanya konsekuensi dari utas independen yang memiliki sumber daya yang secara teknis harus muncul di pohon. Saya tidak bisa melihat apa pun untuk menyarankan bahwa pertukaran itu sendiri berkontribusi langsung ke masalah kebuntuan.
sumber
Jika ini adalah kebuntuan pencarian klasik , daftar sumber daya akan mencakup kedua Indeks Clustered dan Non-Clustered Index. Biasanya SELECT akan menahan kunci SHARED pada indeks NC dan menunggu kunci SHARED pada CI, sementara itu INSERT akan mendapatkan kunci EKSKLUSIF pada CI dan menunggu kunci EKSKLUSIF pada NC. Daftar sumber daya di deadlock xml akan mencantumkan kedua objek ini dalam kasus ini.
Karena grafik jalan buntu hanya melibatkan Indeks NC, kita dapat mengesampingkan opsi itu.
Juga, Jika ini adalah kunci mati karena Nested Loop Bergabung dengan PREFETCH TIDAK BERKUNCI , rencana eksekusi akan memberi tahu kami apakah algoritma PREFETCH TIDAK BERKUNCI yang digunakan, yang lagi-lagi tidak terjadi di sini (lihat pembaruan di bawah).
Itu membuat kita berasumsi bahwa ini adalah jalan buntu karena Rencana Paralel.
Grafik deadlock tidak dirender dengan benar, tetapi jika Anda melihat Deadlock XML, Anda dapat melihat bahwa dua utas dari pernyataan SELECT (SPID 690) terlibat dalam deadlock. Utas konsumen memegang kunci SHARED pada PAGE 1219645 dan menunggu produsen di port801f8ed0 (e_waitPipeGetRow). Utas produsen sedang menunggu kunci bersama di PAGE 1155940.
Pernyataan INSERT memegang kunci IX pada PAGE 1155940 dan menunggu kunci IX pada PAGE 1219645, yang menghasilkan kebuntuan.
Saya percaya bahwa kebuntuan akan dicegah ketika menggunakan paket serial untuk pernyataan SELECT karena pada titik mana pun akan membutuhkan kunci SHARED pada lebih dari satu halaman. Saya juga berpikir bahwa rencana serial akan hampir sama dengan rencana paralel (bukan operator paralelisme).
[DIPERBARUI berdasarkan komentar Paul]
Rupanya rencana tersebut menggunakan algoritma Nested Loop OPTIMIZED
Itu menjelaskan mengapa kunci SHARED ditahan hingga akhir pernyataan. BACA ULANG dikombinasikan dengan rencana paralel lebih rentan terhadap kebuntuan daripada rencana seri karena rencana paralel mungkin mendapatkan dan menjaga kunci dari rentang indeks yang berbeda sedangkan rencana serial memperoleh kunci dalam cara yang lebih berurutan.
sumber