SQL Server DB menjadi tidak dapat digunakan dalam semalam

9

Kemarin, database SQL Server saya baik-baik saja. Hari ini hampir tidak dapat digunakan - melambat dengan faktor antara lima hingga dua puluh, tergantung pada saat saya memukulnya.

Beberapa data ditambahkan ke server dalam proses pemuatan semalaman, tetapi tidak seperti volume yang seharusnya memengaruhi banyak basis data. Sekitar 50.000 catatan teks biasa (tidak ada XML atau lainnya).

Server telah ditambal pagi ini sebelum kami reboot. Namun, tidak ada server basis data kami yang lain yang juga ditambal berperilaku berbeda.

Resource Monitor tampaknya menyarankan bahwa IO disk-nya salah. Ini berjalan hampir 100% dari kapasitas pada file .mdf sepanjang waktu, bahkan ketika tidak banyak yang sebenarnya terjadi dalam database. Akses ke Templog.ldf juga berjalan cukup tinggi.

Tidak seorang pun di sini adalah DBA ahli (kita semua pengembang dengan jumlah keterampilan SQL yang beragam) dan kita semua bingung dengan apa yang terjadi. Kami telah mencoba menjalankan sp_updatestats dan memindahkan beberapa indeks besar ke disk yang berbeda, tetapi tidak berhasil.

Saya pikir ini pasti ada hubungannya dengan tambalan - sepertinya terlalu banyak kejadian bersama. Seorang kolega diyakinkan bahwa pemuatan data yang menyebabkan ukuran mdf meningkat ke titik di mana itu menyebabkan rencana eksekusi menjadi tidak efisien.

Apa yang menyebabkan ini? Bagaimana kita bisa mengetahuinya, dan apa yang bisa kita lakukan untuk memperbaikinya?

EDIT:

Menggunakan sp_WhoIsActivemengungkapkan tidak ada yang luar biasa. Ini mendaftar penggunaan sproc saya sendiri dan beberapa perintah dari seorang kolega yang saat ini mencoba untuk memindahkan indeks lain. Itu mungkin menahan DB sekarang tetapi itu berjalan sama buruknya sebelumnya.

Ini adalah versi standar SQL Server 2008 R2. SELECT @@VERSIONmemberi:

Microsoft SQL Server 2008 R2 (SP2) - 10.50.4033.0 (X64)
9 Juli 2014 16:04:25
Hak cipta (c) Microsoft Corporation Edisi Standar (64-bit) pada Windows NT 6.1 (Build 7601: Paket Layanan 1) (Hypervisor )

Server memiliki 72GB RAM dan tiga prosesor 2GHz quad-core.

Penambalan hanya diterapkan pada Windows. Tidak ada perubahan selain tambalan.

Pengaturan yang dipilih:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

UPDATE: Menggeser indeks dan tabel ke partisi disk yang berbeda tampaknya meningkatkan hal-hal. Saya masih bingung bagaimana kita bisa mencapai titik kritis begitu tiba-tiba dengan hasil drastis tersebut.

Bob Tway
sumber
Bisakah Anda menjalankan sp_whoisactive selama 5 menit dan menangkap output ke tabel. Anda dapat mengunduhnya dari sini dan ini akan menunjukkan bagaimana Anda dapat menangkap output ke tabel
Kin Shah
Nah, jika Anda me-restart server, itu berarti semua data cache Anda dibuang dari buffer pool, dan semua rencana eksekusi cache Anda dibuang juga. Ini berarti bahwa SQL Server harus meningkatkan keduanya - setiap rencana eksekusi harus dikompilasi ulang, dan jika statistik basi Anda mungkin tidak mendapatkan paket yang paling efisien. Ini juga berarti data harus dibaca ke dalam memori dari disk, sedangkan sebelum restart mungkin bersenandung bersama dengan data dalam memori. Ini harus berumur pendek.
Aaron Bertrand
@ AaronBertrand Sudah seperti ini selama delapan jam. Kami secara teratur me-reboot server untuk penambalan dan belum pernah melihat yang seperti ini sebelumnya.
Bob Tway
1
Jangan gunakan UI untuk memeriksa pengaturan konfigurasi. SELECT * FROM sys.configurations;- Anda ingin value, value_in_usehal-hal seperti max server memory (MB). Juga nomor build di SELECT @@VERSION;akan berguna, serta apakah ini di hypervisor dan jika ada yang berubah pada host sejak kemarin (atau sejak terakhir kali SQL Server restart).
Aaron Bertrand
2
Apa jenis subsistem IO yang Anda gunakan? SAN, disk lokal, dll? Apakah ada kemungkinan drive Anda rusak? Apakah ada DB yang disimpan di lokasi yang sama dengan file OS? Dan pertanyaan terakhir. Bagian dari proses kami sebelum melakukan peningkatan OS adalah mengambil snapshot VM sebelumnya. Sayangnya orang yang bertanggung jawab lupa untuk melakukan itu. Sangat cepat seluruh sistem menjadi semakin lambat. Adakah kemungkinan ini terjadi pada Anda?
Kenneth Fisher

Jawaban:

3

Itu bisa terjadi bahwa sejumlah kecil data mencapai batas tertentu di SQL Server untuk memaksa rencana lain atau sesuatu seperti itu. Ini bukan tidak mungkin. Tetapi fakta bahwa disk Anda tampaknya sedang dalam tugas membawa saya ke kesimpulan lain.

Ada 2 alasan dasar yang mungkin untuk memperlambat Anda.

  1. Anda memutakhirkan sistem Anda dan menyalakannya kembali
  2. Anda memuat banyak data di dalamnya

Mari kita lihat bagian No. 1

Mungkin konfigurasi SQL Server Anda mungkin rusak. Ini dapat menyebabkan masalah serius terkait kecepatan Server Anda dan penggunaan disk.

Silakan periksa pada contoh pertama pengaturan server dasar Anda. Mereka pengaturan dasar max server memory, affinity I/O mask, affinity maskdan max degree of parallelism. Anda mungkin perlu mengaktifkan opsi lanjutan menggunakan show advanced options.

Berikut ini skrip lengkap:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

Bandingkan hasilnya dengan nilai yang Anda dokumentasikan pada langkah instalasi Anda. Apakah mereka masih sama?

Mungkin ada banyak alasan mengapa server Anda berperilaku sangat aneh. Saya biasanya bertaruh, bahwa Anda max server memorysalah. Ini akan menyebabkan SQL Server Anda bertukar halaman data secara permanen. Dia tidak bisa menyimpan semuanya dalam ingatannya. Ini berarti dia perlu membaca halaman dari disk, memperbaruinya, menulisnya kembali secara instan. Jika pembaruan lain datang dan menggunakan halaman yang sama untuk pembaruan, itu tidak dapat dibaca dari memori. Sebaliknya server perlu membacanya lagi dari disk. Hanya bertukar ...

Masalah lain dapat menjadi afinitas tinggi pada disk atau proses. Jika Anda menggunakan Server bersama (SQL Server + layanan lain) dengan disk khusus untuk SQL Server (yang mungkin jarang terjadi, tetapi bisa jadi), ini bisa menjadi masalah Anda. Server Anda biasanya memiliki misalnya 3 cpus untuk proses dan satu untuk I / O. 12 cpus lainnya digunakan untuk layanan lain. Dalam hal ini topeng afinitas Anda salah dan menggunakan misalnya konfigurasi otomatis. Ini berarti Server Anda menggunakan semua 16 core untuk proses dan I / O secara dinamis. Jika Anda memiliki proses besar yang sedang berjalan, mereka dapat menempatkan beban yang sangat besar pada disk, yang mungkin tidak ditangani. Tetapi pada kenyataannya, saya tidak percaya bahwa ini adalah kasus Anda. Akan lebih cepat (bahkan jika hanya sedikit) jika ini akan berlaku, tetapi kasing Anda lambat.

Masalah lain mungkin adalah tingkat paralelisme yang terlalu tinggi. Yang berarti Anda memiliki terlalu banyak utas yang menganggur di satu bagian dari kueri. Ini juga dapat menyebabkan pelambatan besar jika paralelisme tidak berfungsi seperti yang diharapkan. Tapi ini tidak akan menjelaskan I / O tinggi Anda secara total.

Sekarang mari kita lihat bagian no 2 juga

Anda memuat banyak baris ke dalam sistem Anda. Bahkan jika ini adalah pekerjaan biasa, itu bisa meningkatkan batas di mana rencana kueri Anda meningkat. Bisa jadi ini kasus bahwa sisipan Anda dalam kombinasi dengan SQL Server menghasilkan perilaku ini.

Anda menyebutkan bahwa Anda sudah mencoba memigrasi indeks Anda ke disk lain, yang sepertinya membantu. Ini dapat terjadi hanya karena Anda membagi beban pada dua disk yang berbeda.

Mungkin saja indeks Anda retak, bahwa rencana Anda retak atau bahwa statistik Anda baru saja kedaluwarsa.

1. mari kita periksa statistik pembaruan terakhir Anda dapat melakukan ini secara manual melalui antarmuka untuk setiap elemen statistik tunggal. Itu akan menyebalkan. Atau Anda dapat mencoba kode ini:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

Ini akan memberi Anda informasi lengkap tentang setiap indeks (dan tumpukan) dan statistik di belakangnya. Bahkan jika Anda menjalankannya, sp_updatestatsitu tidak berarti bahwa statistik diperbarui. Bagian ketika pembaruan cukup rumit, bahkan jika Anda menjalankan sp_updatestatsatau bahkan jika auto update statisticsdiaktifkan, statistik tidak akan diperbarui tepat waktu. Berikut adalah beberapa poin tepi, ketika pembaruan diperlukan / dibuat:

  • Meja kosong mendapat satu atau lebih baris
  • Tabel dengan lebih dari 500 baris memperbarui 20% + 500 baris tambahan dan penyisipan terjadi setelahnya
  • Ketika 500 baris diubah dalam tabel yang menampung kurang dari 500 baris

Ini berarti, statistik Anda mungkin kedaluwarsa walaupun Anda menjalankan pembaruan.

Anda dapat melihat permintaan di atas. Jika Anda menemukan beberapa statistik yang cukup lama di beberapa tabel, Anda mungkin ingin menjalankan pembaruan statistik manual untuk tabel ini:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Setelah itu, Anda mungkin ingin memberikan tendangan ke server Anda untuk membuang semua rencana lama.

DBCC FREEPROCCACHE 

Jika Anda hanya ingin membersihkan semua cache, Anda mungkin ingin menjalankan ini sebagai gantinya:

DBCC FREESYSTEMCACHE ('ALL')

Ini akan membersihkan semua cache, bukan hanya cache rencana. Saya biasanya memperingatkan, untuk menggunakan ini pada server produksi dalam fase produksi. Tetapi karena server Anda tidak berfungsi saat ini, Anda tidak dapat terlalu membahayakan mereka. Mungkin memperlambat selama beberapa detik mungkin 1-2 menit karena dia perlu membangun kembali semua cache, tetapi setelah itu dia harus menjalankan dengan rencana yang benar.

Alasan lain adalah indeks yang benar-benar terfragmentasi. Ini dapat diperiksa di seluruh server menggunakan pernyataan ini:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

Jika fragmentasi sangat tinggi, Anda mungkin perlu mengatur ulang (fragmentasi <20%) atau membangun kembali total (> 20%). Ini mungkin membutuhkan lebih banyak tekanan pada disk Anda dan menyebabkan masalah. Di sisi lain, jika indeksnya seburuk itu, mungkin pada akhirnya akan lebih membantu daripada merugikan.

Selain dua alasan itu, mungkin masih ada masalah ketiga

Mungkin server Anda dikonfigurasi mungkin, Anda belum mengubah kode apa pun saat ini, hanya menambahkan beberapa baris. Semua statistik diperbarui dan semua cache dibangun kembali. Semua indeks Anda ditata ulang sesuai dengan kebutuhan Anda, tetapi tetap saja - tidak ada yang berhasil. Mungkin saja Anda mencapai batas memori yang tersedia dalam proses Anda. Mungkin Anda membutuhkan lebih banyak. Anda cukup memeriksa apakah ada proses yang mencoba mendapatkan lebih banyak memori daripada yang Anda miliki.

Anda dapat memeriksanya menggunakan perintah ini:

SELECT * FROM sys.dm_exec_query_memory_grants

Ini akan memberi Anda daftar semua sesi yang menghabiskan memori. Mungkin ada beberapa permintaan yang masih menunggu untuk mendapatkan memori. Pertanyaan-pertanyaan itu dapat dengan mudah disaring. Semua sesi ada di mana granted_memory_kb IS NULL. Ini adalah sesi yang meminta memori tetapi tidak mendapatkannya. Hal lain dapat berupa memori yang diberikan yang mungkin rendah. Anda dapat membandingkan kolom requested_memory_kbdengan granted_memory_kb. Diminta menunjukkan berapa banyak memori yang diperlukan untuk menjalankan proses secara optimal sementara diberikan menunjukkan memori yang memungkinkan untuk proses. Jika suatu proses membutuhkan 2GB untuk dijalankan tetapi hanya mendapat 2MB ... Anda mungkin mendapatkannya sendiri. ;-)

Cara lain adalah dengan memeriksa RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Anda dapat melihat waiter_countdan grantee_count. Jika pelayan di atas 0, Anda memiliki tekanan pada memori Anda, yang dapat menyebabkan swapping dan dapat menyebabkan tekanan disk terlihat oleh Anda di perfmon.

Ionik
sumber
0

Selain kemungkinan kegagalan drive, periksa status subsistem RAID Anda. Kami melihat sesuatu yang serupa dan ternyata baterai pada pengontrol RAID gagal sehingga tidak ada cache tulis yang tersedia - semua penulisan harus langsung masuk ke disk. Satu catatan samping - kita bisa merasakan sistem berhenti sementara RDC ke dalamnya.

William Jens
sumber