லினக்ஸில் Powershell இலிருந்து MS SQL உடன் பணிபுரிதல்

இந்த கட்டுரை முற்றிலும் நடைமுறை மற்றும் எனது சோகமான கதைக்கு அர்ப்பணிக்கப்பட்டுள்ளது

தயாராகிறது ஜீரோ டச் PROD RDS (MS SQL) க்காக, எங்கள் எல்லா காதுகளும் ஒலித்துக் கொண்டிருந்தன, நான் ஒரு விளக்கக்காட்சியை (POC - ப்ரூஃப் ஆஃப் கான்செப்ட்) உருவாக்கினேன்: பவர்ஷெல் ஸ்கிரிப்ட்களின் தொகுப்பு. விளக்கக்காட்சிக்குப் பிறகு, புயலடித்த, நீடித்த கைதட்டல் குறைந்து, இடைவிடாத கைதட்டலாக மாறியபோது, ​​அவர்கள் என்னிடம் சொன்னார்கள் - இவை அனைத்தும் நல்லது, ஆனால் கருத்தியல் காரணங்களுக்காக மட்டுமே, எங்கள் ஜென்கின்ஸ் அடிமைகள் அனைவரும் லினக்ஸில் வேலை செய்கிறார்கள்!

இது சாத்தியமா? விண்டோஸின் கீழ் இருந்து அத்தகைய சூடான, விளக்கு DBA ஐ எடுத்து லினக்ஸின் கீழ் பவர்ஷெல் வெப்பத்தில் ஒட்டவா? இது கொடுமையல்லவா?

லினக்ஸில் Powershell இலிருந்து MS SQL உடன் பணிபுரிதல்
தொழில்நுட்பங்களின் இந்த விசித்திரமான கலவையில் நான் மூழ்க வேண்டியிருந்தது. நிச்சயமாக, எனது 30+ ஸ்கிரிப்ட்கள் வேலை செய்வதை நிறுத்திவிட்டன. எனக்கு ஆச்சரியமாக, ஒரே வேலை நாளில் எல்லாவற்றையும் சரிசெய்ய முடிந்தது. நான் சூடான தேடலில் எழுதுகிறேன். எனவே, பவர்ஷெல் ஸ்கிரிப்ட்களை விண்டோஸிலிருந்து லினக்ஸுக்கு மாற்றும்போது நீங்கள் என்னென்ன ஆபத்துகளைச் சந்திக்கலாம்?

sqlcmd vs Invoke-SqlCmd

அவற்றுக்கிடையேயான முக்கிய வேறுபாட்டை நான் உங்களுக்கு நினைவூட்டுகிறேன். நல்ல பழைய பயன்பாடு sqlcmd இது லினக்ஸின் கீழும் கிட்டத்தட்ட ஒரே மாதிரியான செயல்பாட்டுடன் செயல்படுகிறது. -Q ஐ இயக்க வினவலை அனுப்புகிறோம், உள்ளீட்டு கோப்பை -i ஆகவும், வெளியீட்டை -o ஆகவும் அனுப்புகிறோம். ஆனால் கோப்பு பெயர்கள், நிச்சயமாக, வழக்கு உணர்திறன் செய்யப்படுகின்றன. நீங்கள் -i ஐப் பயன்படுத்தினால், கோப்பில் இறுதியில் எழுதவும்:

GO
EXIT

இறுதியில் EXIT இல்லை என்றால், sqlcmd உள்ளீட்டிற்காக காத்திருக்கும், மற்றும் அதற்கு முன் வெளியேறு மாட்டேன் GO, கடைசி கட்டளை வேலை செய்யாது. வெளியீட்டு கோப்பில் அனைத்து வெளியீடு, தேர்வுகள், செய்திகள், அச்சு, முதலியன உள்ளன.

Invoke-SqlCmd ஆனது DataSet, DataTables அல்லது DataRows என முடிவை உருவாக்குகிறது. எனவே, ஒரு எளிய தேர்வின் முடிவை நீங்கள் செயலாக்கினால், நீங்கள் பயன்படுத்தலாம் sqlcmd, அதன் வெளியீட்டைப் பாகுபடுத்தி, சிக்கலான ஒன்றைப் பெறுவது கிட்டத்தட்ட சாத்தியமற்றது: இதற்காக உள்ளது அழைப்பு-SqlCmd. ஆனால் இந்த அணிக்கு அதன் சொந்த நகைச்சுவைகளும் உள்ளன:

  • நீங்கள் ஒரு கோப்பை அவளுக்கு மாற்றினால் -உள்ளீடு கோப்பு, பின்னர் வெளியேறு தேவையில்லை, மேலும், இது தொடரியல் பிழையை உருவாக்குகிறது
  • - வெளியீடு கோப்பு இல்லை, கட்டளை ஒரு பொருளாக முடிவை உங்களுக்கு வழங்குகிறது
  • சேவையகத்தைக் குறிப்பிட இரண்டு தொடரியல்கள் உள்ளன: -ServerInstance -பயனர்பெயர் -கடவுச்சொல் - தரவுத்தளம் மற்றும் மூலம் -இணைப்பு சரம். விந்தை போதும், முதல் வழக்கில் 1433 ஐத் தவிர வேறு ஒரு துறைமுகத்தைக் குறிப்பிட முடியாது.
  • உரை வெளியீடு, PRINT என தட்டச்சு செய்யவும், இது வெறுமனே "பிடிபட்டது" sqlcmdஐந்து அழைப்பு-SqlCmd ஒரு பிரச்சனை
  • மற்றும் மிக முக்கியமாக: பெரும்பாலும் உங்கள் லினக்ஸில் இந்த 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 புறக்கணிக்கப்பட்டது. யு அழைப்பு-SqlCmd புறக்கணிக்கப்பட்டது - மாறிகள். மாறிகளைக் குறிப்பிடும் அளவுரு புறக்கணிக்கப்பட்டாலும், மாற்றீடுகள் தாங்களாகவே செயல்படுகின்றன - ஷெல்லில் இருந்து எந்த மாறிகளையும் நீங்கள் பயன்படுத்தலாம். இருப்பினும், நான் மாறிகளால் புண்படுத்தப்பட்டேன், மேலும் 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 ஐப் பெற்றேன், மேலும் ஒரு கோப்பில் பிரத்யேக பூட்டை எடுக்கும் முயற்சியின் காரணமாக UNC வழியாக BULK INSERT வேலை செய்யாது, மேலும் 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 (அடையாளம்) வரிசையில் தேர்ந்தெடுக்கவும்.

அடுத்த கட்டுரையில், இவை அனைத்தும் ஜென்கின்ஸ் உடன் எவ்வாறு தொடர்பு கொள்கின்றன என்பதைப் பற்றி மேலும் விரிவாகப் பேசுவேன்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்