Deskripsi masalah
Deadlock dapat terjadi ketika aplikasi sering membaca atau menulis data ke tabel atau sumber daya pada instance ApsaraDB RDS for SQL Server. Saat deadlock terjadi, instance RDS menghentikan salah satu transaksi dan mengirimkan pesan kesalahan kepada klien yang memulai transaksi tersebut. Pesan kesalahan yang dikirim mirip dengan berikut:
Pesan Kesalahan: Msg 1205, Level 13, State 47, Line 1Transaksi (Process ID 53) mengalami deadlock pada sumber daya kunci bersama dengan proses lain dan telah dipilih sebagai korban deadlock. Jalankan ulang transaksi.Solusi
Hubungkan ke instance RDS dari klien. Untuk informasi lebih lanjut, lihat Hubungkan ke instance ApsaraDB RDS for SQL Server.
Pantau tampilan terkait.
Jalankan pernyataan SQL berikut untuk memantau tampilan
SYS.SYSPROCESSESsecara berkala:WHILE 1 = 1 BEGIN SELECT * FROM SYS.SYSPROCESSES WHERE BLOCKED <> 0; WAITFOR DELAY '[$Time]'; END;Catatan[$Time]menentukan interval pemantauan. Dalam contoh ini, digunakan nilai00:00:01.Gambar berikut menunjukkan contoh keluaran:
CatatanDalam keluaran, kolom
blockedmenunjukkan ID sesi yang memblokir sesi saat ini, sedangkan kolomwaitresourcemenunjukkan sumber daya yang ditunggu oleh sesi yang diblokir. Pada contoh ini, sesi 53 dan sesi 56 saling memblokir, menyebabkan deadlock. spid menunjukkan ID sesi.Jalankan pernyataan SQL berikut untuk memantau tampilan
sys.dm_tran_locksdansys.dm_os_waiting_taskssecara berkala:while 1=1 Begin SELECT db.name DBName, tl.request_session_id, wt.blocking_session_id, OBJECT_NAME(p.OBJECT_ID) BlockedObjectName, tl.resource_type, h1.TEXT AS RequestingText, h2.TEXT AS BlockingText, tl.request_mode FROM sys.dm_tran_locks AS tl INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 waitfor delay '[$Time]' EndGambar berikut menunjukkan contoh keluaran:

Tabel berikut menjelaskan parameter respons:
Parameter
Deskripsi
DBNameNama database yang sesi yang diblokir mencoba akses.
request_session_idID sesi dalam permintaan saat ini. Sesi tersebut adalah sesi yang diblokir.
blocking_session_idID sesi pemblokiran.
BlockedObjectNameObjek yang dikelola oleh sesi yang diblokir.
resource_typeJenis sumber daya yang sesi tunggu.
RequestingTextPernyataan yang dieksekusi dalam sesi. Pernyataan tersebut adalah pernyataan yang diblokir.
BlockingTextPernyataan yang dieksekusi dalam sesi pemblokiran.
request_modeMode kunci yang diminta oleh sesi.
Jika instance RDS Anda menggunakan SQL Server 2012, Anda juga dapat menggunakan SQL Server Profiler untuk memantau deadlock dan menghasilkan grafik deadlock.

Gambar berikut menunjukkan grafik deadlock:

Saran optimasi
Anda dapat melakukan langkah-langkah berikut untuk optimasi:
Hentikan sesi pemblokiran untuk menyelesaikan masalah pemblokiran.
Periksa apakah ada transaksi yang belum dikomit dalam waktu lama. Jika ada, segera komit transaksi tersebut.
Jika kueri diblokir karena kunci bersama dan aplikasi Anda mengizinkan dirty read, gunakan petunjuk kueri
WITH (NOLOCK). Sebagai contoh, jalankan pernyataanSELECT * FROM table WITH (NOLOCK);. Dengan cara ini, kueri tidak akan mengajukan permohonan kunci untuk mencegah masalah deadlock.Periksa logika aplikasi untuk memastikan akses ke sumber daya dilakukan secara berurutan.
Referensi
Anda dapat melihat deadlock dari instance RDS di Konsol ApsaraDB RDS. Untuk informasi lebih lanjut, lihat Lihat statistik deadlock.