Ag obair le MS SQL bho Powershell air Linux

Tha an artaigil seo dìreach practaigeach agus tha e coisrigte don sgeulachd bhrònach agam

Ag ullachadh airson Zero Touch PROD airson RDS (MS SQL), air an robh na cluasan againn uile beò, rinn mi taisbeanadh (POC - Proof Of Concept) de fèin-ghluasad: seata de sgriobtaichean slige cumhachd. Às deidh an taisbeanaidh, nuair a bhàsaich am moladh stoirmeil, fada, a’ tionndadh gu bhith na thoileachas neo-sheasmhach, dh’ innis iad dhomh - tha seo uile math, ach dìreach airson adhbharan ideòlach, tha na tràillean Jenkins againn uile ag obair air Linux!

A bheil seo comasach? Gabh DBA lampa cho blàth bho bhith fo Windows agus cuir a-steach e ann am fìor theas slige cumhachd fo Linux? Nach eil seo cruaidh?

Ag obair le MS SQL bho Powershell air Linux
B’ fheudar dhomh mo bhogadh anns a’ chothlamadh neònach seo de theicneòlasan. Gu dearbh, sguir na 30+ sgriobtaichean agam ag obair. Gu mo iongnadh, fhuair mi air a h-uile càil a chàradh ann an aon latha obrach. Tha mi a’ sgrìobhadh ann an tòir teth. Mar sin, dè na duilgheadasan a thig ort nuair a ghluaiseas tu sgriobtaichean slige cumhachd bho Windows gu Linux?

sqlcmd vs Invoke-SqlCmd

Leig leam do chuimhneachadh air a 'phrìomh eadar-dhealachadh eatorra. Deagh sheann ghoireas sqlcmd Bidh e cuideachd ag obair fo Linux, le gnìomhachd cha mhòr co-ionann. Bidh sinn a’ dol seachad air a’ cheist gus -Q a chuir an gnìomh, am faidhle cuir a-steach mar -i, agus an toradh mar -o. Ach tha ainmean nam faidhlichean, gu dearbh, air an dèanamh mothachail air cùis. Ma chleachdas tu -i, sgrìobh san fhaidhle aig an deireadh:

GO
EXIT

Mura h-eil EXIT ann aig an deireadh, an uairsin thèid sqlcmd air adhart gus feitheamh ri cuir a-steach, agus ma tha e roimhe Exit cha dèan GO, an uairsin chan obraich an àithne mu dheireadh. Anns an fhaidhle toraidh tha a h-uile toradh, taghadh, teachdaireachdan, clò-bhualadh, msaa.

Bidh Invoke-SqlCmd a’ toirt a-mach an toradh mar DataSet, DataTables no DataRows. Mar sin, ma làimhsicheas tu toradh taghadh sìmplidh, faodaidh tu a chleachdadh sqlcmd, an dèidh dha an toradh a pharsadh, cha mhòr nach eil e comasach rudeigin iom-fhillte fhaighinn: oir tha seo ann Cuir a-steach-SqlCmd. Ach tha na fealla-dhà fhèin aig an sgioba seo cuideachd:

  • Ma ghluaiseas tu faidhle thuice tro -InputFile, an uairsin Exit chan eil feum air, a bharrachd air sin, bidh e a’ toirt a-mach mearachd co-chòrdadh
  • -OutputFile chan e, tillidh an àithne an toradh dhut mar nì
  • Tha dà cho-chòrdadh ann airson frithealaiche a shònrachadh: -ServerInstance -Username -Password -Database agus troimhe -CeangalString. Gu h-annasach gu leòr, sa chiad chùis chan eil e comasach port a shònrachadh a bharrachd air 1433.
  • toradh teacsa, dèan seòrsa PRINT, a tha dìreach “air a ghlacadh” sqlcmdairson Cuir a-steach-SqlCmd tha duilgheadas
  • Agus as cudromaiche: Is dòcha nach eil an cmdlet seo aig do Linux!

Agus is e seo am prìomh dhuilgheadas. Is ann dìreach sa Mhàrt an cmdlet seo ri fhaighinn airson àrd-ùrlaran neo-Windows, agus mu dheireadh is urrainn dhuinn gluasad air adhart!

Ionadail caochlaideach

Tha ionadachadh caochlaideach aig sqlcmd a’ cleachdadh -v, mar eisimpleir mar seo:

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

Anns an sgriobt SQL bidh sinn a’ cleachdadh luchd-ionaid:

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

Mar sin tha e an seo. Anns *nix chan eil luchd-ionaid caochlaideach ag obair. Paramadair -v air an dearmad. U Cuir a-steach-SqlCmd air an dearmad -Caochlaideach. Ged a tha am paramadair a tha a’ sònrachadh nan caochladairean fhèin air a leigeil seachad, bidh na h-ionadan fhèin ag obair - faodaidh tu caochladairean sam bith a chleachdadh bho Shell. Ach, chuir na caochladairean oilbheum dhomh agus cho-dhùin mi gun a bhith an urra riutha idir, agus rinn mi gnìomh gu mì-mhodhail agus prìomhadail, leis gu bheil na sgriobtaichean SQL goirid:

# 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"

Tha seo, mar a thuigeas tu, na dheuchainn mu thràth bhon dreach Unix.

A 'luchdachadh suas faidhlichean

Ann an dreach Windows, bha sgrùdadh an cois gnìomhachd sam bith: ruith sinn sqlcmd, fhuair sinn seòrsa de dhroch dhìol anns an fhaidhle toraidh, cheangail sinn am faidhle seo ris a’ chlàr sgrùdaidh. Gu fortanach, bha frithealaiche SQL ag obair air an aon fhrithealaiche ri Jenkins, chaidh rudeigin mar seo a dhèanamh:

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

Mar sin, bidh sinn a’ slugadh am faidhle BCP gu tur agus ga ghluasad a-steach don raon nvarchar (max) den chlàr sgrùdaidh. Gu dearbh, thuit an siostam gu lèir seo às a chèile, oir an àite frithealaiche SQL fhuair mi RDS, agus chan eil BULK INSERT ag obair idir tro UNC air sgàth oidhirp glas sònraichte a ghabhail air faidhle, agus le RDS tha seo mar as trice air a dhìteadh bho an toiseach. Mar sin chuir mi romham dealbhadh an t-siostaim atharrachadh le bhith a’ stòradh an sgrùdaidh loidhne air loidhne:

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

Agus sgrìobh mar seo sa chlàr seo:

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() 
  }  

Gus susbaint a thaghadh, feumaidh tu taghadh le ID, a’ taghadh òrdugh n (dearbh-aithne).

Anns an ath artaigil thèid mi a-steach nas mionaidiche air mar a tha seo uile ag eadar-obrachadh le Jenkins.

Source: www.habr.com

Cuir beachd ann