Ți se dau cheile unui SQL Server pe care nu l-ai mai văzut niciodată. „Spune-ne ce nu e în regulă cu el până la ora 17.”
Lecția de față e checklist-ul de 30 de minute pe care îl rulez. Fiecare interogare, în ordine, cu lucrul pe care îl cauți și ce să faci dacă-l găsești. E lecția de încheiere a cursului pentru că reunește tot ce am acoperit. Poți să o printezi. Poți să o lipești în trusa ta. În ziua în care un client nou îți dă un SQL Server, scoți asta și ești productiv într-o jumătate de oră.
Mulțumesc că ai rămas alături prin 40 de lecții. Să încheiem cu o singură rulare scriptată prin întreaga trusă DBA.
Pasul 1 — Prezentarea generală a serverului (2 minute)
SELECT
@@SERVERNAME,
@@VERSION,
SERVERPROPERTY('Edition'),
SERVERPROPERTY('ProductVersion'),
SERVERPROPERTY('MachineName'),
cpu_count, hyperthread_ratio, physical_memory_kb / 1024 AS physical_memory_mb,
sqlserver_start_time
FROM sys.dm_os_sys_info;
Cauți:
- Versiunea SQL Server — ideal 2019+.
- Ediția — Enterprise deblochează mai multe funcționalități.
- Uptime — dacă < 1 săptămână, wait stats și cache-ul vor induce în eroare.
- Memoria — compară cu setarea
max server memory.
Pasul 2 — sp_Blitz (5 minute)
EXEC sp_Blitz;
Citește constatările de prioritate 1–20. Triaj:
- P1 „Niciun backup” → repară imediat.
- P1 „Coruperi” → repară chiar acum, vezi lecția 31.
- P10 „Parolă slabă cont SA” → notează, ridică la securitate.
- P50 ciudățenii de configurare → documentează, repară mai târziu.
Pasul 3 — Recovery model și starea backup-urilor (2 minute)
SELECT d.name,
d.recovery_model_desc,
DATEDIFF(HOUR, MAX(CASE WHEN bs.type = 'D' THEN bs.backup_finish_date END), GETDATE()) AS hours_since_last_full,
DATEDIFF(HOUR, MAX(CASE WHEN bs.type = 'L' THEN bs.backup_finish_date END), GETDATE()) AS hours_since_last_log
FROM sys.databases AS d
LEFT JOIN msdb.dbo.backupset AS bs ON bs.database_name = d.name
WHERE d.name NOT IN ('tempdb')
GROUP BY d.name, d.recovery_model_desc;
Cauți:
- FULL recovery fără backup de log recent → log-ul se umple; repară sau treci pe SIMPLE.
- SIMPLE recovery pe o bază de date critică → confirmă că e intenționat.
- Niciun backup full în > 48 de ore → programează unul acum.
Pasul 4 — Configurația tempdb (1 minut)
SELECT name, size * 8 / 1024 AS size_mb, growth, is_percent_growth, type_desc
FROM tempdb.sys.database_files;
Cauți:
- Un singur fișier de date → adaugă mai multe (unul per vCPU până la 8).
is_percent_growth = 1cu valori mici → schimbă pe MB absoluți.- Mărimi mici → pre-crește la o mărime de lucru așteptată.
Pasul 5 — Wait stats (3 minute)
(Interogarea filtrată din lecția 36.) Cauți:
PAGEIOLATCH_*în top → disc lent sau buffer pool subdimensionat.LCK_*în top → probleme de blocaj, vezi Pasul 8.CXPACKETîn top → probleme de paralelism; probabil neurgent.ASYNC_NETWORK_IOîn top → aplicația citește lent sau seturi uriașe de rezultate.SOS_SCHEDULER_YIELDmare → presiune pe CPU.
Top waits-urile definesc următoarea investigație.
Pasul 6 — sp_BlitzFirst pentru wait stats live (2 minute)
EXEC sp_BlitzFirst @ExpertMode = 1;
Eșantion de 5 secunde din activitatea curentă. Îți spune ce se întâmplă chiar acum (vs cumulativ de la repornire).
Pasul 7 — Top interogări scumpe (3 minute)
USE DBA;
EXEC sp_BlitzCache @Top = 20, @SortOrder = 'CPU';
EXEC sp_BlitzCache @Top = 20, @SortOrder = 'Reads';
Citește coloana de warnings. Infractori comuni:
- Conversie implicită → repară interogarea sau tipul coloanei.
- Predominanță de key lookup → adaugă un index acoperitor.
- Parameter sniffing → recompilează sau forțează din Query Store.
- Spilluri în tempdb → mai multă memorie sau index mai bun.
Pasul 8 — Blocaje curente și activitate live (1 minut)
EXEC sp_WhoIsActive @find_block_leaders = 1, @get_plans = 1;
Cauți:
- Blocatori cu rulare lungă → decide dacă să-i omori.
- Sesiuni sleeping cu tranzacții deschise → zombie; omoară.
- Interogări active grele → corelează cu top CPU.
Pasul 9 — Audit de indecși (5 minute)
USE Runehold; -- ajustează pentru fiecare bază utilizator
EXEC sp_BlitzIndex;
Cauți:
- P1 „Indecși duplicat” → șterge duplicatele.
- Tabele heap → adaugă index clustered.
- Indecși nefolosiți → candidați la ștergere (verifică în timp).
- Sugestii de indecși lipsă → evaluează, alege câteva cu impact mare.
Pasul 10 — Postura Query Store (1 minut)
SELECT name, is_query_store_on
FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');
Dacă vreo bază de date utilizator are Query Store oprit, pornește-l (lecția 28). Fără el, nu poți găsi ușor regresii mai târziu.
Pasul 11 — Creșterea fișierelor și utilizarea discului (2 minute)
SELECT DB_NAME(mf.database_id) AS db, mf.name, mf.type_desc,
mf.size * 8 / 1024 AS size_mb, mf.growth, mf.is_percent_growth
FROM sys.master_files AS mf
WHERE mf.database_id > 4
ORDER BY size_mb DESC;
Cauți:
- Fișiere de log cu
is_percent_growth = 1→ schimbă pe MB absoluți. - Creștere fixă mică (de ex. 10 MB) → mărește la o valoare sensibilă.
- Cele mai mari baze de date → confirmă spațiu de manevră pe disc.
Pasul 12 — Sănătatea joburilor Agent (2 minute)
SELECT TOP (20)
j.name, h.step_id,
CASE h.run_status
WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Cancelled' WHEN 4 THEN 'In Progress' END AS status,
CONVERT(VARCHAR, msdb.dbo.agent_datetime(h.run_date, h.run_time), 120) AS run_time,
h.message
FROM msdb.dbo.sysjobhistory AS h
JOIN msdb.dbo.sysjobs AS j ON j.job_id = h.job_id
ORDER BY h.run_date DESC, h.run_time DESC;
Cauți:
- Eșecuri recente la backup sau joburi de mentenanță.
- Joburi care n-au mai rulat de mult (program dezactivat? Agent oprit?).
- Joburi „In Progress” care ar fi trebuit să se termine acum o oră.
Pasul 13 — Verifică prezența Ola Hallengren + First Responder Kit (1 minut)
SELECT OBJECT_SCHEMA_NAME(object_id) + '.' + name AS proc_name
FROM DBA.sys.procedures
WHERE name IN ('IndexOptimize', 'DatabaseBackup', 'DatabaseIntegrityCheck',
'sp_Blitz', 'sp_BlitzIndex', 'sp_BlitzCache',
'sp_BlitzFirst', 'sp_WhoIsActive');
Instalează orice lipsește. Minute petrecute foarte bine.
Pasul 14 — Istoric de deadlock-uri (1 minut)
-- Din lecția 20
SELECT TOP (10)
XEvent.value('(@timestamp)[1]', 'DATETIME2') AS ts,
XEvent.query('.') AS deadlock_xml
FROM (
SELECT CAST(target_data AS XML) AS td
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
WHERE s.name = 'system_health' AND st.target_name = 'ring_buffer'
) AS source
CROSS APPLY td.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS X(XEvent)
ORDER BY ts DESC;
Cauți deadlock-uri recente. Dacă > 1 pe zi, e ceva ce merită rezolvat.
Pasul 15 — Scrie raportul (5 minute)
Ia notițele și transformă-le într-un raport scurt:
Health check SQL Server Runehold — 2026-04-16
- Per ansamblu: Galben. Trei constatări P1.
- Critice:
- BD
Sales_archiveîn recovery FULL fără backup de log de 7 zile. Fișierul de log 87% folosit. Repară azi. - Niciun backup pe
Reporting_Stagingde 48 de ore. Motiv: jobul AgentStage Backupdezactivat. Reactivează.
- BD
- Mari:
- tempdb are 1 fișier de date pe un server cu 8 nuclee. Contenție PAGELATCH așteptată. Adaugă încă 7 fișiere.
- Conversie implicită în top interogarea CPU
sp_GetOrdersByCountry. Repară tipul de date.
- Medii:
- 22% din indecșii non-clustered nefolosiți de 30+ zile. Evaluează ștergeri.
- Query Store dezactivat pe 3 baze utilizator. Activează.
- Mici:
- Parolă veche
sa(politica spune rotație la 90 de zile). Rotește. - 140+ rânduri de istoric de joburi Agent mai vechi de un an în msdb. Curăță.
- Parolă veche
- De urmărit:
- Programează un drill trimestrial de restaurare.
- Instalează scripturile Ola Hallengren.
- Migrează de la SQL 2019 la 2022 — deja suportat.
Asta e livrabilul tău. Scurt, acționabil, prioritizat.
Ce urmează după acest curs
Acum cunoști echivalentul a un an de experiență la job pe SQL Server, comprimat în 40 de lecții. Ce urmează:
- Citește blogul lui Brent Ozar — articole noi săptămânal pe tot ce ține de SQL Server. Cu opinii, practic, amuzant.
- Blogul lui Paul Randal la SQLskills — analize tehnice profunde pe motorul de stocare, coruperi și DBCC. Expertul pe internals.
- Blogul și videourile lui Erik Darling — sfaturi cu opinie pe tunarea interogărilor, multă magie cu CTE-uri și funcții window.
brentozar.com/training— echipa lui Brent ține cursuri de training. Excelente dacă îți permiți sau dacă plătește angajatorul.- Contribuie la open source — scripturile lui Ola, First Responder Kit,
sp_WhoIsActiveacceptă pull requests. - Exersează pe o sarcină reală — un sandbox cu Adventure Works sau cu setul tău de date. Rulează health check-ul. Repară constatările. Repetă lunar.
Felicitări
Ai parcurs 40 de lecții de SQL Server. Acum cunoști:
- Motorul (Modulele 1–3).
- Indexarea și performanța (Modulele 4–5).
- Stocarea și partiționarea (Modulul 6).
- Esențialele DBA — backup-uri, Agent, securitate, tempdb, mentenanță, DMV-uri (Modulul 7).
- Trusa de urgență — First Responder Kit și
sp_WhoIsActive(Modulul 8).
Dacă acest curs și-a făcut treaba, ești gata să deschizi un SQL Server pe care nu l-ai mai văzut, să-l diagnostichezi în 30 de minute, să rezolvi problemele de top și să nu plângi la 3 dimineața când îți dă ping. Asta e ștacheta. Asta înseamnă „să cunoști SQL Server” la acest nivel.
Du-te și ai grijă de sistemele tale de producție. Depind de tine.
— Mulțumesc că ai citit. Dacă ai văzut greșeli, ai sugestii sau vrei să te cerți pe MERGE, salută.