Sleeping SPID memblokir transaksi lainnya

16

Saya benar-benar mengalami kesulitan melacak beberapa pemblokiran yang kita alami.

Root blocking status SPID 'tidur', cmd adalah 'AWAITING COMMAND', dan sqltextitu SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Ketika saya melihat transaksi teratas oleh laporan jumlah transaksi yang diblokir, pernyataan SQL yang diblokir adalah '-'.

Saya telah melakukan penelusuran pada SQL dan ketika pemblokiran terjadi, menelusuri SPID pemblokiran root tetapi belum benar-benar membawa saya ke mana pun. Pernyataan jejak terakhir sama dengan yang di sqltextatas SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Saya telah memeriksa semua prosedur tersimpan terkait yang dapat saya temukan untuk memastikan mereka memiliki TRY / CATCH BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN pernyataan (kami menggunakan prosedur tersimpan untuk semuanya sehingga tidak ada pernyataan mandiri yang dijalankan). Masalah ini baru mulai terjadi selama 24 jam terakhir dan tidak ada yang mengklaim telah melakukan perubahan pada sistem.

Solusi: salah satu prosedur tersimpan kami yang jarang digunakan memiliki kesalahan dengan sisipan (jumlah kolom tidak cocok), tetapi kami masih bingung tentang apa yang sebenarnya terjadi.

Saat melihat semua informasi penelusuran, pernyataan EXEC untuk prosedur tersimpan ini terdaftar beberapa kali, tetapi TIDAK PERNAH tepat sebelum BLOK terjadi pada SPID pemblokiran. Tampaknya ketika mulai memblokir, jejak tidak mencatat eksekusi (atau pernyataan di dalamnya). Namun ada kalanya jejak itu merekam eksekusi itu dan tidak ada pemblokiran yang terjadi.

Laporan kesalahan prosedur tersimpan berasal dari pengguna, dan saya bisa menemukan beberapa pernyataan EXEC di jejak dan menjalankannya di SSMS. Tidak ada waktu ketika saya menjalankannya kita memiliki pemblokiran atau mereka menggantung. Mereka berlari seperti yang diharapkan (blok penahan menembak dan memutar kembali transaksi setelah kesalahan). Setelah menyelesaikan perbaikan prosedur tersimpan, kami belum melihat masalah lagi.

Brad
sumber
Saya berasumsi nama host SPID pemblokiran tidak membantu sama sekali?
Jon Seigel
Tidak, ini hanya IP dari salah satu server web kami ... Kami memiliki ide lain untuk mengubah setiap login SQL untuk setiap panggilan SPROC selama proses login / registrasi (yang kami rasakan adalah tempat terjadinya kesalahan) menjadi nama pengguna terpisah yang mungkin membantu kami mengisolasi SPROC mana yang dapat menyebabkan pemblokiran.
Brad
1
TRY / CATCH tidak akan menangkap kesalahan kompilasi dan insert kolom yang tidak cocok akan menjadi kesalahan kompilasi. Ini juga tidak akan pernah memicu banyak acara profiler XX: Completed.
Remus Rusanu
1
Sebenarnya ini bukan kesalahan kompilasi dalam kasus ini karena pengembang jenius menggunakan INSERT INTO [table] SELECT * dari [othertable] dan tidak tertangkap secara peer. Saya menjalankan SPROC pada Pengembangan 1000 kali dari ColdFusion dalam 3 sesi simultan dan tidak pernah membiarkan transaksi terbuka seperti pada Produksi.
Brad

Jawaban:

10

Dari komentar, saya menduga Anda memiliki batas waktu Command sisi klien yang telah membatalkan kueri SQL. Ini tidak mengembalikan transaksi karena koneksi tetap terbuka di SQL Server karena koneksi pooling.

Jadi, Anda perlu menggunakan SET XACT_ABORT ON atau menambahkan beberapa kode kembalikan klien

Lihat Timeout Transaksi SQL Server untuk semua detail berdarah

gbn
sumber
Semua SPROC kami berisi TRY / CATCH blok dan BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN pernyataan, ROLLBACK berada di CATCH. Apakah XACT_ABORT masih berpengaruh?
Brad
@Brad: ya. Lihat tautan saya. Blok tangkapan tidak mengenai CommandTimeout
gbn 8'13
gbn: Terima kasih. Saya masih bingung. Koneksi kami disetel ke tidak pernah habis (0). Jadi Anda mengatakan jika kami menggunakan kembali koneksi, dan koneksi menjalankan SPROC dengan kesalahan (yang memiliki blok TRY / CATCH dan TRAN), entah bagaimana ia tidak pernah dapat menjalankan ROLLBACK di blok CATCH sehingga mengunci tabel dan menjaga transaksi Buka? Itu tidak masuk akal bagi saya.
Brad
@Brad: SPROC dengan kesalahan akan mengenai blok CATCH. Saya tidak mengatakan sebaliknya atau berbeda. Tetapi tautan saya menyatakan apa yang terjadi jika Anda memiliki CommandTimeout, yang berbeda dengan ConnectionTimeout. Klien mengatakan "batalkan" dan SQL Server berhenti memproses. Ergo, blok CATCH atau rollback atau commit tidak pernah
tercapai
Saya tidak berpikir kita memiliki CommandTimeout yang ditentukan. Semua prosedur tersimpan kami sedang menguji menggunakan sqlstress dan harus melakukan di bawah 1000 ms pada 10 pengguna 10 iterasi (minimal). Saya masih sangat bingung tentang apa yang telah terjadi, tetapi saya memperbarui pertanyaan dengan apa yang kami temukan adalah masalahnya.
Brad
9

Gunakan most_recent_sql_handle di sys.dm_exec_connections untuk melihat pernyataan terakhir yang dieksekusi.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

Periksa juga apakah ada transaksi terbuka untuk spid itu

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid
Sebastian Meine
sumber
Anda juga bisa menggunakan DBCC INPUTBUFFER(spid)untuk melihat SQL terakhir dieksekusi.
Mike Fal
Saya telah menggunakan semua itu dan perintah terakhir selalu apa yang saya letakkan di posting asli saya: SET TINGKAT ISOLASI TRANSAKSI BACA BERKOMITMEN. Saya juga menjalankan DBCC OPENTRAN dan dapat melihat bahwa ada transaksi terbuka untuk PID yang diblokir.
Brad
Pilihan pertama saya juga memberi Anda nama prosedur, jika pernyataan itu memang bagian dari prosedur.
Sebastian Meine
Saya yakinkan Anda, kami tidak menggunakan permintaan adhoc dari server web kami, dan ketika saya menjalankan kueri pertama itu, bahkan tanpa klausa WHERE, saya hanya mendapatkan SPROC bernama pada beberapa sesi SQL, sisanya kolom itu NULL.
Brad
Saya memperhatikan bahwa saya memiliki banyak sesi yang mengatakan 'SET TINGKAT ISOLASI TRANSAKSI BACA BERKOMITMEN' dan semuanya berasal dari ColdFusion (skrip utama yang digunakan pada server web kami). Mungkin ColdFusion ketika menganggur mengeluarkan pernyataan bahwa untuk menahan membuka koneksi (karena diatur untuk menjaga koneksi tetap terbuka).
Brad
4

Sudahkah Anda mencoba menggunakan sp_whoisactive Adam Machanic ? Ada opsi untuk mendapatkan perintah luar untuk melihat apakah itu benar-benar ada dalam proc. Bisa jadi aplikasi tersebut menahan transaksi terbuka daripada melakukan itu. Coba lihat DBCC OPENTRAN juga.

Eric Humphrey - lotahelp
sumber
Terima kasih untuk DBCC OPENTRAN. Itu memberitahu saya bahwa PID pemblokiran memiliki transaksi terbuka, tetapi tidak ada rincian lebih lanjut tersedia. sp_whoisactive mengembalikan informasi yang sama tentang proses yang diblokir seperti yang saya dapatkan sendiri. Masih belum ada perincian tentang apa yang terjadi selain 'SET TINGKAT ISOLASI TRANSAKSI BACA BERKOMITMEN'
Brad