PILIH / MASUKKAN Deadlock


10

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


2
Apa proc_InsertEventReceiverdan proc_InsertContextEventReceivermelakukan 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?
Aaron Bertrand

1
Saya ingin tahu apa pengaturan MAXDOP Anda yang luas dan berapa banyak prosesor (logis) yang Anda miliki. SharePoint benar-benar berfungsi lebih baik dan lebih suka berada di server dengan server MAXDOP lebar 1 .. Saya tidak menyukainya, tapi itulah cara mereka mengembangkannya. Bisakah Anda memposting rencana eksekusi yang sebenarnya? Yang saya lihat di tautan itu adalah .xdl (grafik deadlock)
Mike Walsh

Halo Tuan-tuan, saya sangat menghargai Anda meluangkan waktu, dari jadwal sibuk Anda untuk merespons. Saya akan memposting prosedur dan rencana eksekusi untuk ulasan Anda di situs SkyDrive. Saya telah berpikir tentang memodifikasi kode untuk memasukkan opsi permintaan MAXDOP (1), namun demikian, hal itu akan membatalkan dukungan kami dengan Microsoft. Server fisik adalah pengaturan ProLiant DL580 G4 MAXDOP adalah 4 dengan total 8 prosesor fisik dan H / T dinonaktifkan.
SQLJarHead

Halo Tuan-tuan, saya telah membuat paket zip dengan semua detail di SkyDrive. Saya memodifikasi isi postingan asli untuk memasukkan URL paket. Tolong, jangan beri tahu saya apa masalahnya, berikan saja panduan dan minta saya bekerja untuk itu. CATATAN: Saya tidak dapat membuat perubahan kode atau modifikasi DDL ke skema yang mendasarinya.
SQLJarHead

1
Jadi, Anda tidak dapat mengubah kode dan Anda tidak dapat mengubah skema, solusi apa lagi yang Anda harapkan dari kami? Jika Anda khawatir tentang membatalkan dukungan Microsoft, maka itu menyiratkan bahwa Anda memiliki dukungan Microsoft, dalam hal ini - mengingat semua pembatasan yang Anda katakan kepada kami bahwa Anda tidak dapat melakukannya - sudahkah Anda mempertimbangkan untuk membuka tiket dukungan dengan Microsoft?
Aaron Bertrand

Jawaban:


14

Di wajah itu, ini tampak seperti jalan buntu pencarian klasik . Bahan-bahan penting untuk pola kebuntuan ini adalah:

  • sebuah SELECTquery yang menggunakan indeks nonclustered non-covering dengan Lookup Key
  • sebuah INSERTquery yang memodifikasi indeks berkerumun dan kemudian indeks nonclustered

The SELECTmengakses indeks nonclustered pertama, maka indeks berkerumun. The INSERTakses 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, SELECTkueri adalah:

PILIH kueri

... dan INSERTkueri adalah:

Masukkan pertanyaan

Perhatikan pemeliharaan indeks non-clustered yang disorot hijau.

Kita perlu melihat versi serial dari SELECTrencana 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 READselama 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 1perilaku 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.


6

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.


Sepakat. Jika kebuntuan ini terkait dengan LOOKUP aktual, sumber daya tunggu, untuk SELECT, akan merujuk indeks berkerumun. Saya dapat mengesampingkannya dengan menampilkan tajuk halaman untuk setiap sumber daya menunggu (SPID 690 Sumber Daya Tunggu = HALAMAN: 1155940 | SPID 356 Sumber Daya Tunggu = HALAMAN 1219645) melalui HALAMAN DBCC dan keduanya berada pada indeks ID 5 (IndexID 5 = EventReceivers_ByContextObjectId) yang menunjuk ke indeks NC pada tabel yang ditentukan (EventReceivers).
SQLJarHead

Tuan-tuan, Sekali lagi terima kasih telah meluangkan waktu untuk membantu menganalisis masalah yang menarik ini. Beberapa pertanyaan: 1.) Roji menunjukkan bahwa SPID paralel meminta lebih dari satu halaman. Saya tidak melihat itu dalam rencana eksekusi. Melihat jumlah baris, untuk operator INDEKS SEEK, hanya satu utas dari dua produsen yang memproses setiap baris. Bagaimana Anda menentukan bahwa ia meminta lebih dari satu halaman? (1/2)
SQLJarHead

2.) Apakah algoritma Nested Loop yang dioptimalkan akan selalu mengatur level isolasi ke REAPTABLE READ? Saya telah memeriksa rencana eksekusi output XML dan saya hanya melihat read berkomitmen untuk koneksi SPID. Saya membuat asumsi ini hanya dipanggil pada level operator paket saja. (2/2)
SQLJarHead

Perilaku penguncian Nested Loops yang DIOPTIMALKAN sebanding dengan REPEATABLE READ (menjaga kunci sampai akhir pernyataan ), tetapi tidak jelas mengatur tingkat isolasi transaksi ke REPEATABLE READ. Saya pikir itu menjawab satu pertanyaan Anda juga. Bukan berarti utas paralel meminta lebih dari satu halaman pada suatu waktu, tetapi satu utas paralel memegang kunci pada satu halaman dan utas lainnya sedang menunggu kunci pada halaman lain
Roji P Thomas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.