Ħidma ma 'MS SQL minn Powershell fuq Linux

Dan l-artikolu huwa purament prattiku u huwa ddedikat għall-istorja mwiegħra tiegħi

Tħejjija għal Zero Touch PROD għal RDS (MS SQL), li dwaru l-widnejn kollha tagħna kienu żanżin, għamilt preżentazzjoni (POC - Proof Of Concept) ta 'awtomazzjoni: sett ta' skripts powershell. Wara l-preżentazzjoni, meta l-applaws imqalleb u fit-tul miet, u nbidel f'applaws bla waqfien, qaluli - dan kollu huwa tajjeb, iżda biss għal raġunijiet ideoloġiċi, l-iskjavi kollha tagħna Jenkins jaħdmu fuq Linux!

Dan huwa possibbli? Ħu tali sħun, fanal DBA minn taħt Windows u waħħalha fil-sħana stess ta 'powershell taħt Linux? Dan mhux krudili?

Ħidma ma 'MS SQL minn Powershell fuq Linux
Kelli ngħaddas ruħi f'din il-kombinazzjoni stramba ta 'teknoloġiji. Naturalment, l-iskripts kollha tiegħi ta '30+ waqfu jaħdmu. B'sorpriża tiegħi, irnexxieli nirranġa kollox f'ġurnata tax-xogħol waħda. Qed nikteb fi hot pursuit. Allura, liema nases tista 'tiltaqa' magħhom meta tittrasferixxi skripts powershell mill-Windows għal Linux?

sqlcmd vs Invoke-SqlCmd

Ħa nfakkarkom fid-differenza ewlenija bejniethom. Utilità qadima tajba sqlcmd Taħdem ukoll taħt Linux, b'funzjonalità kważi identika. Aħna ngħaddu l-mistoqsija biex tesegwixxi -Q, il-fajl tal-input bħala -i, u l-output bħala -o. Iżda l-ismijiet tal-fajls, ovvjament, isiru sensittivi għall-każ. Jekk tuża -i, imbagħad fil-fajl ikteb fl-aħħar:

GO
EXIT

Jekk ma jkunx hemm ĦRUĠ fl-aħħar, allura sqlcmd jipproċedi biex jistenna l-input, u jekk qabel ĦRUĠ mhux se GO, allura l-aħħar kmand ma jaħdimx. Il-fajl tal-produzzjoni fih l-output kollu, tagħżel, messaġġi, stampar, eċċ.

Invoke-SqlCmd jipproduċi r-riżultat bħala DataSet, DataTables jew DataRows. Għalhekk, jekk tipproċessa r-riżultat ta 'għażla sempliċi, tista' tuża sqlcmd, wara li parsed l-output tiegħu, huwa kważi impossibbli li tiġi derivata xi ħaġa kumplessa: għal dan hemm Invoka-SqlCmd. Iżda dan it-tim għandu wkoll iċ-ċajt tiegħu stess:

  • Jekk tittrasferixxi fajl lilha permezz -InputFile, Imbagħad ĦRUĠ mhux meħtieġ, barra minn hekk, jipproduċi żball ta' sintassi
  • -OutputFile le, il-kmand jagħtik ir-riżultat bħala oġġett
  • Hemm żewġ sintassi biex jiġi speċifikat server: -ServerInstance -Username -Password -Database u permezz -ConnectionString. B'mod stramb, fl-ewwel każ mhuwiex possibbli li jiġi speċifikat port għajr 1433.
  • output tat-test, ittajpja PRINT, li hija sempliċement "maqbuda" sqlcmdgħal Invoka-SqlCmd hija problema
  • U l-aktar importanti: X'aktarx il-Linux tiegħek m'għandux dan is-cmdlet!

U din hija l-problema ewlenija. Biss f'Marzu dan is-cmdlet sar disponibbli għal pjattaformi mhux Windows, u fl-aħħar nistgħu nimxu 'l quddiem!

Sostituzzjoni Varjabbli

sqlcmd għandu sostituzzjoni varjabbli bl-użu -v, pereżempju bħal dan:

# $conn содержит начало команды sqlcmd
$cmd = $conn + " -i D:appsSlaveJobsKillSpid.sql -o killspid.res 
  -v spid =`"" + $spid + "`" -v age =`"" + $age + "`""
Invoke-Expression $cmd

Fl-iskrittura SQL nużaw sostituzzjonijiet:

set @spid=$(spid)
set @age=$(age)

Allura hawnhekk huwa. F'*nix sostituzzjonijiet varjabbli ma jaħdmux. Parametru -v injorat. U Invoka-SqlCmd injorat -Varjabbli. Għalkemm il-parametru li jispeċifika l-varjabbli nfushom huwa injorat, is-sostituzzjonijiet infushom jaħdmu—tista 'tuża kwalunkwe varjabbli minn Shell. Madankollu, kont offiż mill-varjabbli u ddeċidejt li ma niddependi fuqhom xejn, u aġixxa b'mod goff u primittiv, peress li l-iskripts SQL huma qosra:

# prepend the parameters  
"declare @age int, @spid int" | Add-Content "q.sql"
"set @spid=" + $spid | Add-Content "q.sql"
"set @age=" + $age | Add-Content "q.sql"

foreach ($line in Get-Content "Sqlserver/Automation/KillSpid.sql") { 
  $line | Add-Content "q.sql" 
  }
$cmd = "/opt/mssql-tools/bin/" + $conn + " -i q.sql -o res.log"

Dan, kif tifhem, huwa test diġà mill-verżjoni Unix.

Ittella' fajls

Fil-verżjoni tal-Windows, kwalunkwe operazzjoni kienet akkumpanjata minn verifika: aħna dam sqlcmd, irċevejna xi tip ta 'abbuż fil-fajl tal-output, mehmuż dan il-fajl mal-pjanċa tal-verifika. Fortunatament, SQL server ħadem fuq l-istess server bħal Jenkins, sar xi ħaġa bħal din:

CREATE procedure AuditUpload
  @id int, @filename varchar(256)
as
  set nocount on
  declare @sql varchar(max)

  CREATE TABLE #multi (filer NVARCHAR(MAX))
  set @sql='BULK INSERT #multi FROM '''+@filename
    +''' WITH (ROWTERMINATOR = '' '',CODEPAGE = ''ACP'')'
  exec (@sql)
  select @sql=filer from #multi
  update JenkinsAudit set multiliner=@sql where ID=@id
  return

Għalhekk, aħna nibla 'l-fajl BCP għal kollox u shove fil-qasam nvarchar(max) tat-tabella tal-verifika. Naturalment, din is-sistema kollha waqgħet, għax minflok SQL server sibt RDS, u BULK INSERT ma taħdimx xejn permezz tal-UNC minħabba tentattiv biex tieħu lock esklussiv fuq fajl, u b'RDS dan ġeneralment huwa kkundannat minn il-bidu nett. Allura ddeċidejt li nibdel id-disinn tas-sistema, u naħżen il-verifika linja b'linja:

CREATE TABLE AuditOut (
  ID int NULL,
  TextLine nvarchar(max) NULL,
  n int IDENTITY(1,1) PRIMARY KEY
  )

U ikteb f'din it-tabella hekk:

function WriteAudit([string]$Filename, [string]$ConnStr, 
     [string]$Tabname, [string]$Jobname)
{
  # get $lastid of the last execution  -- проскипано для статьи
	
  #create grid and populate it with data from file
  $audit =  Get-Content $Filename
  $DT = new-object Data.DataTable   

  $COL1 =  new-object Data.DataColumn; 
  $COL1.ColumnName = "ID"; 
  $COL1.DataType =  [System.Type]::GetType("System.Int32") 

  $COL2 =  new-object Data.DataColumn; 
  $COL2.ColumnName = "TextLine"; 
  $COL2.DataType =  [System.Type]::GetType("System.String") 
  
  $DT.Columns.Add($COL1) 
  $DT.Columns.Add($COL2) 
  foreach ($line in $audit) 
    { 
    $DR = $dt.NewRow()   
    $DR.Item("ID") = $lastid
    $DR.Item("TextLine") = $line
    $DT.Rows.Add($DR)   
    } 

  # write it to table
  $conn=new-object System.Data.SqlClient.SQLConnection 
  $conn.ConnectionString = $ConnStr
  $conn.Open() 
  $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnStr
  $bulkCopy.DestinationTableName = $Tabname 
  $bulkCopy.BatchSize = 50000
  $bulkCopy.BulkCopyTimeout = 0
  $bulkCopy.WriteToServer($DT) 
  $conn.Close() 
  }  

Biex tagħżel il-kontenut, trid tagħżel b'ID, tagħżel fl-ordni n (identità).

Fl-artiklu li jmiss ser nidħol f'aktar dettall dwar kif dan kollu jinteraġixxi ma 'Jenkins.

Sors: www.habr.com

Żid kumment