Linux ပေါ်ရှိ Powershell မှ MS SQL နှင့် အလုပ်လုပ်ခြင်း။

ဤဆောင်းပါးသည် လက်တွေ့ကျရုံမျှသာဖြစ်ပြီး ကျွန်ုပ်၏ဝမ်းနည်းဖွယ်ဇာတ်လမ်းအတွက် ရည်ရွယ်ပါသည်။

အတွက် ပြင်ဆင်နေပါသည်။ Zero Touch PROD RDS (MS SQL) အတွက် ကျွန်ုပ်တို့၏နားများ တုန်လှုပ်သွားသည့်အကြောင်း၊ ကျွန်ုပ်သည် အလိုအလျောက်စနစ်၏ သက်သေပြချက် (POC - Proof Of Concept) - powershell scripts အစုံကို ပြုလုပ်ခဲ့သည်။ တင်ဆက်မှုအပြီးတွင်၊ မုန်တိုင်းထန်ပြီး ကြာရှည်သောလက်ခုပ်သံများ ဆုံးပါးသွားကာ အဆက်မပြတ်လက်ခုပ်သံများအဖြစ်သို့ ပြောင်းလဲသွားသောအခါ၊ ၎င်းတို့က ကျွန်ုပ်အား ပြောခဲ့သည် - ဤအရာအားလုံးသည် ကောင်းမွန်သော်လည်း အတွေးအခေါ်ပိုင်းဆိုင်ရာ အကြောင်းပြချက်များကြောင့်သာ၊ ကျွန်ုပ်တို့၏ Jenkins ကျွန်များအားလုံး Linux တွင် အလုပ်လုပ်ပါသည်။

ဒါက ဖြစ်နိုင်လား။ Windows အောက်မှ နွေးထွေးသော DBA မီးခွက်ကို ယူ၍ Linux အောက်တွင် powershell ၏ အပူရှိန်တွင် ကပ်ထားပါသလား။ ဒါ ရက်စက်တာမဟုတ်ဘူးလား။

Linux ပေါ်ရှိ Powershell မှ MS SQL နှင့် အလုပ်လုပ်ခြင်း။
ဒီလို ထူးဆန်းတဲ့ နည်းပညာတွေ ပေါင်းစပ်မှုမှာ ကိုယ့်ကိုယ်ကို နှစ်မြှုပ်ခဲ့ရတယ်။ ဟုတ်ပါတယ်၊ ကျွန်ုပ်၏ 30+ script များအားလုံး အလုပ်မလုပ်တော့ပါ။ အံ့သြဖို့ကောင်းတာက အလုပ်တစ်ရက်တည်းမှာ အရာအားလုံးကို ပြင်ဆင်နိုင်ခဲ့တယ်။ ကျွန်တော် ဇောက်ချ ရေးနေပါသည်။ ထို့ကြောင့်၊ Windows မှ Linux သို့ powershell script များကိုလွှဲပြောင်းသောအခါတွင်သင်ကြုံတွေ့ရသောအခက်အခဲများ။

sqlcmd vs Invoke-SqlCmd

သူတို့ကြားက အဓိက ခြားနားချက်ကို သတိပေးပါရစေ။ ဟောင်းနွမ်း အသုံးဝင်မှု sqlcmd ၎င်းသည် Linux အောက်တွင်လည်း အလားတူ လုပ်ဆောင်နိုင်စွမ်းဖြင့် လုပ်ဆောင်သည်။ -Q၊ input file ကို -i အဖြစ် နှင့် -o အဖြစ် execute လုပ်ရန် query ကို ကျွန်ုပ်တို့ ဖြတ်သန်းပါသည်။ သို့သော် ဖိုင်အမည်များကို အသေးစိပ်ဖြင့် ပြုလုပ်ထားသည်။ -i ကိုသုံးရင် ဖိုင်ရဲ့အဆုံးမှာ ရေးပါ။

GO
EXIT

အဆုံးတွင် EXIT မရှိပါက၊ sqlcmd သည် input ကို စောင့်ဆိုင်းရန် ဆက်လက်လုပ်ဆောင်မည်ဖြစ်ပြီး၊ နှင့် မတိုင်မီ ဖြစ်ပါက၊ ထွက်ပေါက်GOဒါဆိုရင် နောက်ဆုံး command က အလုပ်မလုပ်ပါဘူး။ အထွက်ဖိုင်တွင် အထွက်၊ ရွေးချယ်မှုများ၊ မက်ဆေ့ချ်များ၊ ပရင့်ထုတ်ခြင်း အစရှိသည်တို့ ပါဝင်သည်။

Invoke-SqlCmd သည် DataSet၊ DataTables သို့မဟုတ် DataRows အဖြစ် ရလဒ်ကို ထုတ်လုပ်သည်။ ထို့ကြောင့်၊ သင်သည် ရိုးရှင်းသောရွေးချယ်မှုရလဒ်ကို လုပ်ဆောင်မည်ဆိုပါက၊ သင်သည် အသုံးပြုနိုင်သည်။ sqlcmd၎င်း၏ output ကိုခွဲခြမ်းစိတ်ဖြာပြီး၊ ရှုပ်ထွေးသောအရာတစ်ခုခုကိုရရှိရန်မဖြစ်နိုင်ပေ။ Invoke-SqlCmd. ဒါပေမယ့် ဒီအဖွဲ့မှာလည်း သူ့ဟာသတွေရှိတယ်။

  • ဖိုင်တစ်ဖိုင်ကို သူမထံလွှဲပေးလျှင် -InputFileထိုအခါ ထွက်ပေါက် မလိုအပ်ဘဲ၊ ထို့အပြင်၊ ၎င်းသည် syntax error ကိုဖြစ်ပေါ်စေသည်။
  • -OutputFile မဟုတ်ဘူး၊ အမိန့်က သင့်ရလဒ်ကို အရာဝတ္ထုတစ်ခုအနေနဲ့ ပြန်ပေးတယ်။
  • ဆာဗာတစ်ခုသတ်မှတ်ခြင်းအတွက် syntax နှစ်ခုရှိသည်။ -ServerInstance -Username -Password -Database မှတဆင့် -ConnectionString. ထူးဆန်းသည်မှာ ပထမကိစ္စတွင် 1433 မှလွဲ၍ အခြား port တစ်ခုကို သတ်မှတ်ရန် မဖြစ်နိုင်ပါ။
  • စာသားအထွက်အား၊ ရိုးရှင်းစွာ “ဖမ်း” သည့် PRINT ဟု ရိုက်ထည့်ပါ။ sqlcmdအတွက် Invoke-SqlCmd ပြဿနာတစ်ခုဖြစ်သည်။
  • အရေးအကြီးဆုံးကတော့- သင့် Linux တွင် ဤ cmdlet မရှိပါ။

ပြီးတော့ ဒါက အဓိက ပြဿနာပါ။ မတ်လမှာသာ ဒီ cmdlet ပါ။ Windows မဟုတ်သော ပလပ်ဖောင်းများအတွက် ရရှိလာခဲ့သည်။၊ နောက်ဆုံးတော့ ငါတို့ ရှေ့ကို ဆက်သွားနိုင်တယ်။

ပြောင်းလဲနိုင်သော အစားထိုးမှု

sqlcmd တွင် -v ကို အသုံးပြု၍ ပြောင်းလဲနိုင်သော အစားထိုးမှု ရှိသည်၊ ဥပမာ၊ ဤကဲ့သို့သော

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

SQL script တွင် ကျွန်ုပ်တို့သည် အစားထိုးမှုများကို အသုံးပြုသည်-

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

ဒီတော့ ဒီမှာ။ *nix တွင် ပြောင်းလဲနိုင်သော အစားထိုးမှုများ အလုပ်မလုပ်ပါ။. ကန့်သတ်ချက် -v လျစ်လျူရှုထားသည်။ U Invoke-SqlCmd လျစ်လျူရှုထားသည်။ -ကိန်းရှင်များ. ကိန်းရှင်များကိုယ်တိုင်သတ်မှတ်ပေးသည့် ကန့်သတ်ဘောင်ကို လျစ်လျူရှုထားသော်လည်း အစားထိုးမှုများသည် ၎င်းတို့ကိုယ်တိုင်အလုပ်လုပ်သည်—သင် Shell မှ မည်သည့် variable များကိုမဆို အသုံးပြုနိုင်သည်။ သို့သော်လည်း၊ ကျွန်ုပ်သည် ကိန်းရှင်များကြောင့် စိတ်အနှောင့်အယှက်ဖြစ်ခဲ့ပြီး ၎င်းတို့အပေါ် လုံးဝမှီခိုမနေရန် ဆုံးဖြတ်ခဲ့ပြီး SQL script များသည် တိုတောင်းသောကြောင့်၊ ကြမ်းတမ်းစွာနှင့် ရှေးဦးစွာ ပြုမူခဲ့သည်-

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

သင်နားလည်သည့်အတိုင်း၊ ၎င်းသည် Unix ဗားရှင်းမှ စမ်းသပ်မှုတစ်ခုဖြစ်သည်။

ဖိုင်များတင်ခြင်း။

Windows ဗားရှင်းတွင်၊ မည်သည့်လုပ်ဆောင်ချက်ကိုမဆို စာရင်းစစ်ခြင်းဖြင့် လိုက်ပါသွားသည်- ကျွန်ုပ်တို့သည် sqlcmd ကို run ပြီး output file တွင် အလွဲသုံးစားမှုအချို့ကို လက်ခံရရှိပြီး ဤဖိုင်ကို စာရင်းစစ်ပန်းကန်တွင် တွဲထားသည်။ ကံကောင်းထောက်မစွာ၊ SQL ဆာဗာသည် Jenkins ကဲ့သို့တူညီသောဆာဗာတွင်အလုပ်လုပ်သည်၊ ၎င်းသည်ဤကဲ့သို့သောလုပ်ဆောင်ခဲ့သည်-

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 server အစား 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() 
  }  

အကြောင်းအရာကို ရွေးချယ်ရန်၊ သင်သည် ID ဖြင့် ရွေးချယ်ရန်၊ အမှာစာ n (identity) ကို ရွေးချယ်ရန် လိုအပ်သည်။

နောက်ဆောင်းပါးတွင်၊ ဤအရာအားလုံးသည် Jenkins နှင့် မည်သို့မည်ပုံတုံ့ပြန်ပုံအကြောင်း အသေးစိတ်ကို ကျွန်ုပ်ပြောပါမည်။

source: www.habr.com

မှတ်ချက် Add