ලිනක්ස් හි Powershell වෙතින් MS SQL සමඟ වැඩ කිරීම

මෙම ලිපිය තනිකරම ප්‍රායෝගික වන අතර මගේ දුක්බර කතාවට කැප වේ

සඳහා සූදානම් වෙමින් Zero Touch PROD RDS (MS SQL) සඳහා, අපගේ සියලු කන් ඝෝෂා කළ, මම ස්වයංක්‍රීයකරණය පිළිබඳ ඉදිරිපත් කිරීමක් (POC - සංකල්ප සාධනය) ඉදිරිපත් කළෙමි: පවර්ෂෙල් ස්ක්‍රිප්ට් කට්ටලයක්. ඉදිරිපත් කිරීමෙන් පසු, නොනවතින අත්පොළසන් හඬක් බවට පත් වූ විට, කුණාටු සහිත, දිගු අත්පොළසන් හඬ මැකී ගිය විට, ඔවුන් මට කීවේය - මේ සියල්ල හොඳයි, නමුත් මතවාදී හේතූන් මත පමණක්, අපගේ සියලුම ජෙන්කින්ස් වහලුන් ලිනක්ස් මත වැඩ කරයි!

මෙය කළ හැකිද? එවැනි උණුසුම්, ලාම්පු DBA වින්ඩෝස් යටින් ගෙන එය ලිනක්ස් යටතේ පවර්ෂෙල් තාපය තුළ අලවන්නද? මෙය කුරිරු නොවේද?

ලිනක්ස් හි Powershell වෙතින් MS SQL සමඟ වැඩ කිරීම
මට මේ අමුතු තාක්ෂණයේ සංකලනය තුළ ගිල්වීමට සිදු විය. ඇත්ත වශයෙන්ම, මගේ සියලුම ස්ක්‍රිප්ට් 30+ ක්‍රියා කිරීම නතර විය. පුදුමයට කරුණක් නම්, මම වැඩ කරන දිනයක් තුළ සියල්ල නිවැරදි කිරීමට සමත් විය. මම ලියන්නේ උණුසුම් ලුහුබැඳීමෙනි. ඉතින්, පවර්ෂෙල් ස්ක්‍රිප්ට් වින්ඩෝස් සිට ලිනක්ස් වෙත මාරු කිරීමේදී ඔබට මුහුණ දිය හැකි අන්තරායන් මොනවාද?

sqlcmd එදිරිව Invoke-SqlCmd

ඔවුන් අතර ඇති ප්‍රධාන වෙනස ගැන මම ඔබට මතක් කරමි. හොඳ පැරණි උපයෝගීතාවයක් sqlcmd එය ලිනක්ස් යටතේ ද ක්‍රියා කරයි, බොහෝ දුරට සමාන ක්‍රියාකාරීත්වයකින්. අපි -Q ක්‍රියාත්මක කිරීමට විමසුම ද, ආදාන ගොනුව -i ලෙස ද, ප්‍රතිදානය -o ලෙස ද යමු. නමුත් ගොනු නම්, ඇත්ත වශයෙන්ම, සිද්ධි සංවේදී කර ඇත. ඔබ -i භාවිතා කරන්නේ නම්, ගොනුවේ අවසානයේ ලියන්න:

GO
EXIT

අවසානයේ EXIT නොමැති නම්, sqlcmd ආදානය සඳහා රැඳී සිටීමට සහ පෙර නම් පිටවීම එසේ නොවනු ඇත GO, එවිට අවසාන විධානය ක්රියා නොකරනු ඇත. ප්‍රතිදාන ගොනුවේ සියලුම ප්‍රතිදානය, තේරීම්, පණිවිඩ, මුද්‍රණය යනාදිය අඩංගු වේ.

Invoke-SqlCmd ප්‍රතිඵලය DataSet, DataTables හෝ DataRows ලෙස නිපදවයි. එබැවින්, ඔබ සරල තේරීමක ප්රතිඵලය සකසන්නේ නම්, ඔබට භාවිතා කළ හැකිය sqlcmd, එහි ප්‍රතිදානය විග්‍රහ කිරීමෙන්, සංකීර්ණ දෙයක් ව්‍යුත්පන්න කිරීම පාහේ කළ නොහැක්කකි: මේ සඳහා තිබේ Invoke-SqlCmd. නමුත් මෙම කණ්ඩායමට තමන්ගේම විහිළු ද ඇත:

  • ඔබ ඇය වෙත ගොනුවක් මාරු කරන්නේ නම් - ආදාන ගොනුවඑවිට පිටවීම අවශ්‍ය නොවේ, එපමනක් නොව, එය සින්ටැක්ස් දෝෂයක් ඇති කරයි
  • -ප්‍රතිදාන ගොනුව නැත, විධානය මඟින් ඔබට ප්‍රතිඵලය වස්තුවක් ලෙස ලබා දෙයි
  • සේවාදායකයක් නියම කිරීම සඳහා සින්ටැක්ස් දෙකක් තිබේ: -ServerInstance -පරිශීලක නාමය - මුරපදය - දත්ත සමුදාය සහ හරහා -ConnectionString. පුදුමයට කරුණක් නම්, පළමු අවස්ථාවේ දී 1433 හැර වෙනත් වරායක් සඳහන් කළ නොහැක.
  • පෙළ ප්‍රතිදානය, ප්‍රින්ට් ටයිප් කරන්න, එය සරලව "අල්ලා" sqlcmdසඳහා Invoke-SqlCmd යනු ගැටලුවකි
  • සහ වඩාත්ම වැදගත්: බොහෝ දුරට ඔබගේ Linux හි මෙම cmdlet නොමැත!

සහ ප්රධාන ගැටළුව මෙයයි. මාර්තු මාසයේදී පමණක් මෙම cmdlet වින්ඩෝස් නොවන වේදිකා සඳහා ලබා ගත හැකි විය, සහ අවසානයේ අපට ඉදිරියට යා හැකිය!

විචල්ය ආදේශනය

sqlcmd හි -v භාවිතා කරමින් විචල්‍ය ආදේශනයක් ඇත, උදාහරණයක් ලෙස මේ වගේ:

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

SQL ස්ක්‍රිප්ට් එකේ අපි ආදේශන භාවිතා කරමු:

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

එහෙනම් මෙන්න මේකයි. * නික්ස් හි විචල්‍ය ආදේශන ක්‍රියා නොකරයි. පරාමිතිය -v නොසලකා හැර ඇත. යූ Invoke-SqlCmd නොසලකා හැර ඇත -විචල්‍ය. විචල්‍යයන්ම සඳහන් කරන පරාමිතිය නොසලකා හරිනු ලැබුවද, ආදේශනම ක්‍රියා කරයි—ඔබට Shell වෙතින් ඕනෑම විචල්‍යයක් භාවිතා කළ හැක. කෙසේ වෙතත්, මම විචල්‍යයන් නිසා අමනාප වූ අතර ඒවා මත කිසිසේත් රඳා නොසිටීමට තීරණය කළ අතර SQL ස්ක්‍රිප්ට් කෙටි බැවින් රළු සහ ප්‍රාථමික ලෙස ක්‍රියා කළෙමි:

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

මෙය, ඔබ තේරුම් ගත් පරිදි, යුනික්ස් අනුවාදයෙන් දැනටමත් පරීක්ෂණයකි.

ගොනු උඩුගත කිරීම

වින්ඩෝස් අනුවාදයේ, ඕනෑම මෙහෙයුමක් විගණනයක් සමඟ සිදු විය: අපි sqlcmd ධාවනය කර, ප්‍රතිදාන ගොනුවේ යම් ආකාරයක අපයෝජනයක් ලබා ගත්තා, මෙම ගොනුව විගණන තහඩුවට අමුණා ඇත. වාසනාවකට මෙන්, SQL සේවාදායකය ජෙන්කින්ස් මෙන් එකම සේවාදායකයේ ක්‍රියා කළේය, එය මේ වගේ දෙයක් සිදු කරන ලදී:

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

මේ අනුව, අපි BCP ගොනුව සම්පූර්ණයෙන්ම ගිල දමා එය විගණන වගුවේ nvarchar(max) ක්ෂේත්‍රයට තල්ලු කරමු. ඇත්ත වශයෙන්ම, මෙම මුළු පද්ධතියම කඩා වැටුණි, මන්ද මට SQL සේවාදායකයක් වෙනුවට RDS ලැබුණි, සහ ගොනුවකට සුවිශේෂී අගුලක් ගැනීමට උත්සාහ කිරීම නිසා BULK INSERT UNC හරහා කිසිසේත් ක්‍රියා නොකරයි, සහ RDS සමඟ මෙය සාමාන්‍යයෙන් විනාශ වේ. ආරම්භය. එබැවින් විගණන රේඛාව පේළියකින් ගබඩා කිරීමෙන් පද්ධති සැලසුම වෙනස් කිරීමට මම තීරණය කළෙමි:

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

තවද මෙම වගුවේ මෙසේ ලියන්න:

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

අන්තර්ගතය තේරීමට, n (අනන්‍යතාවය) අනුපිළිවෙලින් තෝරා ID මගින් තෝරාගත යුතුය.

මීළඟ ලිපියෙන් මම මේ සියල්ල ජෙන්කින්ස් සමඟ අන්තර්ක්‍රියා කරන ආකාරය ගැන වඩාත් විස්තරාත්මකව යන්නෙමි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න