Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Дагы аранжировка темасын улантууда Zero Touch PROD RDS астында. Келечектеги DBAлар PROD серверлерине түз туташа албайт, бирок колдоно алышат Jenkins операциялардын чектелген комплекси үчүн жумуштар. DBA жумушка киришет жана бир нече убакыттан кийин бул операциянын аяктагандыгы жөнүндө отчет менен кат алат. Келгиле, бул натыйжаларды колдонуучуга көрсөтүүнүн жолдорун карап көрөлү.

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Жөнөкөй текст

Эң майда-чүйдөсүнөн баштайлы. Биринчи ыкма ушунчалык жөнөкөй болгондуктан, сөз кыла турган эч нерсе жок (автор мындан ары FreeStyle жумуштарын колдонот):

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

sqlcmd бир нерсе кылат жана биз аны колдонуучуга сунуштайбыз. Мисалы, резервдик жумуштар үчүн идеалдуу:

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Баса, RDS камдык көчүрмөсү/калыбына келтирүү асинхрондуу экенин унутпаңыз, андыктан аны күтүшүңүз керек:

declare @rds table
  (id int, task_type varchar(128), database_name sysname, pct int, duration int, 
   lifecycle varchar(128), taskinfo varchar(max) null, 
   upd datetime, cre datetime,
   s3 varchar(256), ovr int, KMS varchar(256) null)
waitfor delay '00:00:20' 
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}'
select @xid=max(id) from @rds

again:
waitfor delay '00:00:02'
delete from @rds
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}' 
# {db} substituted with db name by powershell
select @stat=lifecycle,@info=taskinfo from @rds where id=@xid
if @stat not in ('ERROR','SUCCESS','CANCELLED') goto again

Экинчи ыкма, CSV

Бул жерде баары абдан жөнөкөй:

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Бирок, бул ыкма CSVде кайтарылган маалыматтар "жөнөкөй" болгондо гана иштейт. Эгер сиз, мисалы, TOP N CPU интенсивдүү сурамдарынын тизмесин ушундай жол менен кайтарууга аракет кылсаңыз, CSV суроонун текстинде ар кандай символдор - үтүрлөр, тырмакчалар жана ал тургай сызыктар да камтылышы мүмкүн болгондуктан, "дат басып" калат. Ошондуктан, бизге дагы татаал нерсе керек.

HTMLдеги кооз белгилер

Мен сизге дароо код үзүндүсүн берем

$Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@
  
$Result = invoke-Sqlcmd -ConnectionString $jstr -Query "select * from DbInv" `
  | Select-Object -Property * -ExcludeProperty "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result -eq $null) { $cnt = 0; }
elseif ($Result.getType().FullName -eq "System.Management.Automation.PSCustomObject") { $cnt = 1; }
else { $cnt = $Result.Rows.Count; } 
if ($cnt -gt 0) {
  $body = "<h2>My table</h2>"
  $Result | ConvertTo-HTML -Title "Rows" -Head $header -body $body `
    | Out-File "res.log" -Append -Encoding UTF8
  } else {
    "<h3>No data</h3>" | Out-File "res.log" -Append -Encoding UTF8
  }

Баса, System.Management.Automation.PSCustomObject менен линияга көңүл буруңуз, эгерде тордо так бир сызык болсо, анда кандайдыр бир көйгөйлөр пайда болду. Чечим көп түшүнбөстөн интернеттен алынган. Натыйжада, сиз төмөнкүдөй форматталган чыгарууну аласыз:

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Графиктерди тартуу

Эскертүү: Төмөндө кики код!
SQL серверинде процессорду акыркы N мүнөттө көрсөткөн күлкүлүү суроо бар - Жолдош майор баарын эстейт экен! Бул тестти колдонуп көрүңүз:

DECLARE @ts_now bigint = (SELECT cpu_ticks/(cpu_ticks/ms_ticks) 
  FROM sys.dm_os_sys_info WITH (NOLOCK)); 
SELECT TOP(256) 
  DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS [EventTime],
  SQLProcessUtilization AS [SQLCPU], 
  100 - SystemIdle - SQLProcessUtilization AS [OtherCPU]
FROM (SELECT record.value('(./Record/@id)[1]', 'int') AS record_id, 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') 
    AS [SystemIdle], 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') 
    AS [SQLProcessUtilization], [timestamp] 
  FROM (SELECT [timestamp], CONVERT(xml, record) AS [record] 
  FROM sys.dm_os_ring_buffers WITH (NOLOCK)
  WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' 
    AND record LIKE N'%<SystemHealth>%') AS x) AS y 
ORDER BY 1 DESC OPTION (RECOMPILE);

Эми бул форматты колдонуу ($Fragment өзгөрмө)

<table style="width: 100%"><tbody><tr style="background-color: white; height: 2pt;">
  <td style="width: SQLCPU%; background-color: green;"></td>
  <td style="width: OtherCPU%; background-color: blue;"></td>
  <td style="width: REST%; background-color: #C0C0C0;"></td></tr></tbody>
</table>

Биз каттын негизги бөлүгүн түзө алабыз:

$Result = invoke-Sqlcmd -ConnectionString $connstr -Query $Query `
  | Select-Object -Property * -ExcludeProperty `
  "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result.HasRows) {
  foreach($item in $Result) 
    { 
    $time = $itemEventTime 
    $sqlcpu = $item.SQLCPU
    $other = $itemOtherCPU
    $rest = 100 - $sqlcpu - $other
    $f = $fragment -replace "SQLCPU", $sqlcpu
    $f = $f -replace "OtherCPU", $other
    $f = $f -replace "REST", $rest
    $f | Out-File "res.log" -Append -Encoding UTF8
    }

Кайсы мындай болот:

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Ооба, мырза бузукулук жөнүндө көп билет! Кызыгы, бул код төмөнкүлөрдү камтыйт: Powershell (анын ичинде жазылган), SQL, Xquery, HTML. Өкүнүчтүүсү, биз Javascriptти HTMLге кошо албайбыз (анткени ал жазуу үчүн), бирок Python кодун жылтыратуу (аны SQLде колдонсо болот) ар бир адамдын милдети!

SQL Profiler из чыгаруу

TextData талаасынан улам из CSVге туура келбей турганы анык. Бирок каттардагы трассаны көрсөтүү да таң калыштуу - өлчөмүнөн да, бул маалыматтар көбүнчө андан ары талдоо үчүн колдонулат. Ошондуктан, биз төмөнкүлөрдү жасайбыз: аркылуу чалабыз invoke-SqlCmd белгилүү бир скрипт, анын тереңинде жасалган

select 
  SPID,EventClass,TextData,
  Duration,Reads,Writes,CPU,
  StartTime,EndTime,DatabaseName,HostName,
  ApplicationName,LoginName
   from ::fn_trace_gettable ( @filename , default )  

Кийинки другом DBA тарабынан жеткиликтүү серверде, бардык көрсөтүлгөн мамычаларды кабыл алууга даяр, бош шаблону бар Traces маалымат базасы бар. Бул моделди уникалдуу аталышы бар жаңы таблицага көчүрөбүз:

$dt = Get-Date -format "yyyyMMdd"
$tm = Get-Date -format "hhmmss"
$tableName = $srv + "_" + $dt + "_" + $tm
$copytab = "select * into " + $tableName + " from Model"
invoke-SqlCmd -ConnectionString $tstr -Query $copytab 

Эми биз ага өз изибизди жаза алабыз Data.SqlClient.SqlBulkCopy - Мен жогоруда буга мисал келтирдим. Ооба, TextDataдагы константаларды жаап койсо жакшы болмок:

# mask data
foreach ($Row in $Result)
{ 
  $v = $Row["TextData"]
  $v = $v -replace "'([^']{2,})'", "'str'" -replace "[0-9][0-9]+", '999'
  $Row["TextData"] = $v
}

Биз узундугу бир символдон ашык сандарды 999 менен алмаштырабыз, ал эми бир символдон узунураак саптарды "str" ​​менен алмаштырабыз. Көбүнчө 0дөн 9га чейинки сандар желек катары колдонулат, биз аларга тийбейбиз, ошондой эле бош жана бир символдон турган саптар - 'Y', 'N' ж.б.

Келгиле, жашообузга кандайдыр бир түс кошолу (18+)

Таблицаларда көбүнчө көңүл бурууну талап кылган уячаларды бөлүп көрсөткүңүз келет. Мисалы, ҮЙЛӨГӨН, Фрагментациянын жогорку деңгээли ж.б. Албетте, бул жылаңач SQLде жасалышы мүмкүн, PRINT аркылуу HTML түзүү жана Дженкинсте файлдын түрүн HTML кылып коюу:

declare @body varchar(max), @chunk varchar(max)
set @body='<font face="Lucida Console" size="3">'
set @body=@body+'<b>Server name: '+@@servername+'</b><br>'
set @body=@body+'<br><br>'
set @body=@body+'<table><tr><th>Job</th><th>Last Run</th><th>Avg Duration, sec</th><th>Last Run, Sec</th><th>Last Status</th></tr>'
print @body

DECLARE tab CURSOR FOR SELECT '<tr><td>'+name+'</td><td>'+
  LastRun+'</td><td>'+
  convert(varchar,AvgDuration)+'</td><td>'+
  convert(varchar,LastDuration)+'</td><td>'+
    case when LastStatus<>'Succeeded' then '<font color="red">' else '' end+
      LastStatus+
      case when LastStatus<>'Succeeded' then '</font>' else '' end+
     +'</td><td>'
  from #j2
OPEN tab;  
FETCH NEXT FROM tab into @chunk
WHILE @@FETCH_STATUS = 0  
BEGIN
  print @chunk
  FETCH NEXT FROM tab into @chunk;  
END  
CLOSE tab;  
DEALLOCATE tab;
print '</table>'

Эмне үчүн мен мындай код жаздым?

Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Бирок андан да кооз чечим бар. ConvertTo-HTML клеткаларды боёшубузга жол бербейт, бирок биз муну кийин жасай алабыз. Мисалы, биз фрагментация деңгээли 80ден жана 90дон ашкан уячаларды тандагыбыз келет. Келгиле, стилдерди кошолу:

<style>
.SQLmarkup-red { color: red; background-color: yellow; }
.SQLmarkup-yellow { color: black; background-color: #FFFFE0; }
.SQLmarkup-default { color: black; background-color: white; }
</style>

Суроонун өзүнө биз жасалма тилке кошобуз дароо мурун биз түстөгү тилке. Колонка чакырылышы керек SQLmarkup-бир нерсе:

case  
  when ps.avg_fragmentation_in_percent>=90.0 then 'SQLmarkup-red'
  when ps.avg_fragmentation_in_percent>=80.0 then 'SQLmarkup-yellow'
  else 'SQLmarkup-default' 
  end as [SQLmarkup-1], 
ps.avg_fragmentation_in_percent, 

Эми, Powershell тарабынан түзүлгөн HTMLди алгандан кийин, биз баш тилкеден жасалма тилкени алып салабыз, ал эми маалыматтардын негизги бөлүгүндө биз маанини мамычадан стилге өткөрөбүз. Бул эки гана алмаштыруу менен ишке ашырылат:

$html = $html `
  -replace "<th>SQLmarkup[^<]*</th>", "" `
  -replace "<td>SQLmarkup-(.+?)</td><td>",'<td class="SQLmarkup-$1">'

жыйынтыгы:
Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Элганттуу эмеспи? Жок болсо да, бул түс мага бир нерсени эске салат
Дженкинстеги SQL серверин автоматташтыруу: натыйжаны сонун кайтаруу

Source: www.habr.com

Комментарий кошуу