การซิงค์สองฐานข้อมูลใน SQL Server


16

ฉันมีฐานข้อมูล SQL Server สองฐาน หนึ่งคือไคลเอนต์ (โปรแกรมประยุกต์ของ Windows) และที่สองอยู่บนเซิร์ฟเวอร์ ฉันต้องการซิงค์ฐานข้อมูลทั้งสองนี้บ่อยๆ (เช่นทุก 2 นาที!)

ฉันได้อ่านเกี่ยวกับวิธีการซิงค์ที่แตกต่างกันเช่นการจำลอง, การประทับเวลา, ตารางบันทึกการใช้ทริกเกอร์, Microsoft Sync Framework และอื่น ๆ

ที่จริงฉันไม่ชอบใช้วิธีการซิงค์ซึ่งอาจเป็นกล่องดำ (เช่นการจำลองแบบ) เพราะฉันไม่ต้องการให้ตารางเฉพาะของ SQL Server ถูกบล็อกในขณะที่ฉันกำลังอัปเดตและซิงค์กับเซิร์ฟเวอร์

  1. วิธีใดที่คุณคิดว่าฉันควรใช้ในกรณีเช่นนี้? โปรดจำไว้ว่าทุก ๆ นาทีฉันต้องส่งการเปลี่ยนแปลงตารางหลายครั้งจากไคลเอนต์ไปยังเซิร์ฟเวอร์และดึงข้อมูลการเปลี่ยนแปลงสองตารางจากเซิร์ฟเวอร์

  2. ฉันได้พบวิธีการที่แปลก แต่ใหม่ เป็นไปได้หรือไม่ที่ฉันจะบันทึกขั้นตอนการดำเนินการที่จัดเก็บไว้ทั้งหมด (สำหรับที่ต้องการ) ในไคลเอนต์และส่งพารามิเตอร์ที่มีใน.sqlไฟล์ไปยังเซิร์ฟเวอร์และดำเนินการที่นั่น? จะเกิดขึ้นบนเซิร์ฟเวอร์และส่งไปยังลูกค้า คุณคิดว่านี่เป็นวิธีที่ง่าย แต่มีประโยชน์หรือไม่?

  3. โปรดแนะนำวิธีการที่มีประโยชน์หากคุณทำได้ ขอบคุณมาก.

แก้ไข: โปรดจำไว้ว่านี่เป็นการซิงโครไนซ์แบบเรียลไทม์และทำให้มันพิเศษ หมายความว่าเมื่อผู้ใช้ไคลเอ็นต์กำลังใช้ตารางกระบวนการซิงโครไนซ์กับเซิร์ฟเวอร์จะต้องเกิดขึ้นทุก ๆ นาทีดังนั้นจึงไม่มีการล็อกตารางใด ๆ


1
อย่าลืมว่า "กล่องดำ" เหล่านั้นมีเอกสารค่อนข้างดีเกี่ยวกับวิธีการทำงานวิธีการดูแลรักษาและตรวจสอบและสิ่งที่คุณสามารถทำได้เพื่อแก้ไขปัญหาเหล่านี้ในสถานการณ์ความล้มเหลวทั่วไป (และไม่ใช่เรื่องทั่วไป) ฉันจะพิจารณาวิธีการซิงโครไนซ์ของตัวเองและต้องค้นหาและแก้ไขข้อผิดพลาดที่เกี่ยวข้องกับกรณีขอบว่า "กล่องดำ" ได้ระบุไว้เมื่อนานมาแล้วถ้าหากฉันมีความต้องการเฉพาะแอปพลิเคชันมาก การแก้ไขข้อขัดแย้งเชิงโต้ตอบและอื่น ๆ )
David Spillett

@DavidSpillett: คุณใช้การจำลองแบบในโครงการซิงโครไนซ์ตามเวลาจริงหรือไม่ ข้อกังวลหลักของฉันคือการซิงโครไนซ์แบบเรียลไทม์และ "ล็อคและบล็อก"
Emad Farrokhi

คำตอบ:


14

ฉันอาจไม่ได้ แต่ฉันพยายามตอบมัน

คุณบอกว่าคุณต้องการโซลูชันประสิทธิภาพสูงที่ทำงานบ่อยครั้ง (อย่างน้อย 2 นาที) และคุณต้องการแนวทางที่ดีซึ่งควรรวดเร็วโดยไม่ล็อค แต่คุณไม่ต้องการระบบ blackbox

แทนที่จะเป็นระบบแบล็กบ็อกซ์ที่ใช้กับการติดตั้งหลายล้านครั้งด้วยผลลัพธ์ที่ดีคุณลองคิดค้นวงล้ออีกครั้งและสร้างโซลูชันของคุณเอง? อืมฟังดูแปลกไปหน่อย

อันที่จริงนี่คือคำแนะนำของฉัน

  1. การจำลองแบบแม้ว่าคุณจะบอกว่าคุณจะไม่ใช้มัน มันเป็นวิธีแก้ปัญหาที่ง่ายและดีที่สุดที่คุณสามารถใช้ได้ การจำลองแบบง่ายต่อการติดตั้งทำซ้ำอย่างรวดเร็วและคุณไม่ต้องคิดค้นวงล้ออีก หากคุณเพียงแค่แปลกเกี่ยวกับการล็อกคุณอาจพยายามที่จะตั้งค่าการISOLATION LEVEL READ_COMMITTED_SNAPSHOTคุณสามารถอ่านเพิ่มเติมได้ที่นี่ สิ่งนี้จะใช้เป็นส่วนหนึ่งของ tempdb ของคุณ แต่ตารางของคุณจะอ่านและเขียนได้และการจำลองแบบสามารถทำงานในพื้นหลังได้

ดูตัวอย่างด้านล่าง:

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. CDC (Change Data Capture) สามารถเป็นโซลูชันได้เช่นกัน แต่วิธีนี้คุณต้องสร้างเกือบทุกอย่างด้วยตัวเอง และฉันได้ทำประสบการณ์ที่CDCอาจเป็นสิ่งที่เปราะบางในบางสถานการณ์ CDCจะรวบรวมข้อมูลทั้งหมดในตารางเฝ้าดู (คุณต้องระบุแต่ละตารางที่จับตาดูด้วยตนเอง) หลังจากนั้นคุณจะได้รับความคุ้มค่าก่อนและความคุ้มค่าหลังจากที่INSERT, หรือUPDATE จะระงับข้อมูลเหล่านั้นเป็นระยะเวลาหนึ่ง (คุณสามารถระบุด้วยตัวคุณเอง) วิธีนี้อาจใช้กับบางตารางที่คุณต้องดูและทำซ้ำการเปลี่ยนแปลงเหล่านั้นไปยังฐานข้อมูลอื่นด้วยตนเอง โดยวิธีการใช้การจำลองแบบเซิร์ฟเวอร์ SQL ภายใต้ประทุนเช่นกัน ;-) คุณสามารถอ่านเพิ่มเติมได้ที่นี่DELETECDCCDCCDC

คำเตือน: CDCจะไม่รับรู้ถึงการDDLเปลี่ยนแปลง ซึ่งหมายความว่าหากคุณเปลี่ยนตารางและเพิ่มคอลัมน์ใหม่CDCจะดูตาราง แต่ไม่สนใจการเปลี่ยนแปลงทั้งหมดในคอลัมน์ใหม่ ในความเป็นจริงมันจะบันทึกNULLเป็นค่าก่อนและค่าหลังจากเท่านั้น คุณต้องกำหนดค่าเริ่มต้นใหม่หลังจากDDLเปลี่ยนเป็นตารางที่จับตาดู

  1. วิธีที่คุณอธิบายไว้ข้างต้นเป็นสิ่งที่ต้องการจับภาพปริมาณงานโดยใช้ SQL Server Profiler และรันอีกครั้งบนฐานข้อมูลอื่นสำหรับการวัดประสิทธิภาพบางอย่าง มันสามารถทำงานได้ดี แต่ความจริงที่ว่ามีผลข้างเคียงมากเกินไปนั้นค่อนข้างหนักเกินไปสำหรับฉัน คุณจะทำอย่างไรถ้าคุณจับขั้นตอนการเรียกลูกค้าของคุณ หลังจากนั้นรันคำสั่งเดียวกันที่ฐานข้อมูลหลักของคุณเนื่องจากไม่ซิงค์? กระบวนการนี้อาจทำงานได้ แต่อาจลบ / อัปเดต / แทรกแถวที่ไม่ปรากฏในไคลเอนต์ของคุณ หรือคุณจัดการกับลูกค้าหลายคนด้วยหลักการเดียวได้อย่างไร ฉันคิดว่านี่เป็นเรื่องยุ่งยากเกินไป ในกรณีที่เลวร้ายที่สุดคุณอาจทำลายความซื่อสัตย์ของคุณ
  2. แนวคิดอื่นอาจเป็นไปตามแอปพลิเคชันหรือใช้ทริกเกอร์ ขึ้นอยู่กับจำนวนตารางที่คุณต้องการซิงค์ คุณสามารถเขียนการเปลี่ยนแปลงทั้งหมดไปยังตาราง staging แยกต่างหากและรันงาน SQL Server Agent ทั้งหมด x นาทีเพื่อซิงค์แถวเหล่านั้นในตาราง staging กับต้นแบบของคุณ แต่นี่อาจจะหนักไปหน่อยถ้าคุณพยายามทำการซิงค์ (เช่น) 150 ตาราง คุณจะมีค่าใช้จ่ายใหญ่

นี่คือ 2 เซ็นต์ของฉัน หวังว่าคุณจะได้ภาพรวมที่ดีและบางทีคุณอาจพบวิธีแก้ปัญหาที่เหมาะกับคุณ


9

ฉันจะพยายามระบุตัวเลือกบางอย่างที่นี่พร้อมข้อดีและข้อเสียตามที่ฉันเข้าใจ:

  1. การจำลองแบบเซิร์ฟเวอร์ SQL - นี่คือเครื่องมือ SQL Server แบบเนทีฟที่ดีที่สุดและเหมาะสมที่สุดสำหรับงานนี้ แต่มีปัญหาหลายประการ: สำหรับลูกค้าทั้งหมดของคุณไม่ว่าจะเป็นฐานข้อมูล SQL Express หรือไม่ก็ตามคุณจะต้องมีสิทธิ์การใช้งาน SQL Server CAL สิ่งนี้สามารถหลีกเลี่ยงได้โดยใช้สิทธิ์การใช้งานตัวประมวลผลแต่ละตัว คุณไม่สามารถซิงค์ SQL CE ลูกค้าเป็นต่อที่นี่ ค. SQL Express หรือ LocalDBไม่สามารถทำหน้าที่เป็นผู้เผยแพร่หรือผู้จัดจำหน่ายดังนั้นคุณจึงมีการควบคุมลูกค้าน้อยลงผ่านกระบวนการจำลองแบบ
  2. Microsoft Sync Framework - สำหรับฉันแล้วเหมาะมากสำหรับฐานข้อมูลขนาดเล็กของแอพมือถือ มันเพิ่มตารางค่อนข้างมากในฐานข้อมูลของคุณและไม่มีประสิทธิภาพเท่ากับการจำลองแบบ เนื่องจากมีการใช้งานภายนอก SQL Server เป็นส่วนประกอบจึงเป็นการยากที่จะกำหนดค่า ฉันไม่เคยมีประสบการณ์ลองใช้มันและตัดสินใจที่จะไม่ใช้มัน

  3. การติดตามการเปลี่ยนแปลงฐานข้อมูล มันเป็นฟังก์ชั่น SQL Server ในตัวที่ช่วยให้คุณเปลี่ยนการติดตามรวมถึงการแทรกการอัพเดทและการลบ ทุกอย่างอื่นเช่นการส่งและการใช้การเปลี่ยนแปลงการแก้ไขข้อขัดแย้งเป็นต้นคุณจะต้องเขียนโค้ดด้วยตัวเอง

  4. คอลัมน์ Rowversion (การประทับเวลา)หากคุณไม่อนุญาตให้ลบทั้งหมด (ไม่มีการซิงค์ของบันทึกที่ถูกลบ) - คุณสามารถใช้วิธีการแก้ปัญหาของคุณเองโดยยึดตามข้อมูล rowversion เท่านั้น คอลัมน์ Rowversion ถูกใช้โดยการจำลองแบบเซิร์ฟเวอร์ SQL ด้วยดังนั้นคุณจะต้องเพิ่มคอลัมน์ใด ๆ
  5. CDC ตามที่ระบุไว้ในคำตอบของ Ionic - ฉันไม่มีประสบการณ์เนื่องจากมีเฉพาะในรุ่น Enterprise หรือ Developer เท่านั้น

  6. การใช้กลอุบายของคุณเองในการบันทึกขั้นตอนการจัดเก็บ - ขึ้นอยู่กับลักษณะของแอพพลิเคชันฐานข้อมูลของคุณเป็นอย่างมาก แต่เมื่อกระบวนการแตกต่างกันเล็กน้อยคุณก็จะได้รับข้อมูลจำนวนมาก และคุณจะจัดการกับความขัดแย้งอย่างไร

จากคำถามของคุณดูเหมือนว่าคุณจำเป็นต้องซิงค์เพียงไม่กี่ตารางและไม่ใช่ฐานข้อมูลขนาดใหญ่ทั้งหมด เพื่อจุดประสงค์นี้คุณควรวิเคราะห์ความต้องการของคุณอย่างละเอียดมากกว่าที่คุณระบุไว้ในคำถามเช่น:

  • สามารถลบเกิดขึ้นและเกิดอะไรขึ้นแล้ว?
  • ความขัดแย้งเกิดขึ้นได้อย่างไรป้องกันได้อย่างไรและจะแก้ไขได้อย่างไร?
  • ฉันจะจัดการกับการเปลี่ยนแปลงโครงสร้างตารางได้อย่างไร
  • ...

หากในที่สุดคุณพบว่าการลบและความขัดแย้งไม่ใช่ปัญหาของคุณและโครงสร้างของคุณจะไม่เปลี่ยนแปลงมากนักคุณสามารถลองเขียนตรรกะของคุณเอง แต่มันสามารถเติบโตได้ถึง 1,000 แถวของรหัส


2

ขอบคุณสำหรับคำติชมของคุณ

ฉันประสบความสำเร็จในการแก้ปัญหากระบวนการซิงโครไนซ์โดยการจับขั้นตอนการจัดเก็บที่ดำเนินการแล้วไม่ได้เป็นกลุ่ม เนื่องจากความสมบูรณ์และทุกสิ่งได้รับการพิจารณาอย่างรอบคอบระบบจึงทำงานแบบเรียลไทม์จนถึงปัจจุบัน


เยี่ยมมาก แต่โปรดอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่คุณทำ คุณเพียงแค่บันทึกการโทรของโพรซีเดอร์ที่เก็บไว้ที่ถูกเรียกใช้และเก็บไว้ในเทมเพลต / สคริปต์บางตารางและให้งานรันสคริปต์นี้และตั้งค่าฟิลด์ (เช่นฟิลด์บิตหรือฟิลด์ datetime ที่คุณพูดทั้งหมดนี้ บันทึกที่ยังไม่ได้ประมวลผลและอัปเดตฟิลด์บิตหรือไม่) ฉันดีใจที่คุณแก้ไขปัญหาของคุณ แต่คุณต้องให้ข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับสิ่งที่คุณทำเพื่อช่วยให้ผู้อื่นเรียนรู้?
JonH

0

คำตอบที่ล่าช้า แต่อาจมีประโยชน์สำหรับผู้เข้าชมเธรด

ฉันมีความท้าทายคล้ายกันในการพยายามกระจายข้อมูลข้ามเซิร์ฟเวอร์ที่แตกต่างกันและแก้ไขมันโดยใช้เครื่องมือของบุคคลที่สาม ( Diffสำหรับการเปลี่ยนแปลง schema และDataDiffสำหรับการซิงค์การเปลี่ยนแปลงข้อมูล) และทำตามสคริปต์ PowerShell เพื่อให้กระบวนการทำงานอัตโนมัติ:

#check for the existence of the Outputs folder
function CheckAndCreateFolder($rootFolder, [switch]$Outputs)
{
$location = $rootFolder

#setting up location 
if($Outputs -eq $true)
{
    $location += "\Outputs"
}

#if the folder doesn't exist it will be created
if(-not (Test-Path $location))
{ mkdir $location -Force:$true -Confirm:$false | Out-Null }

return $location
}

#root folder for the schema sync process
$rootFolder = "SchemaSync"

#schema output summaries location 
$outsLoc = CheckAndCreateFolder $rootFolder -Outputs

#ApexSQL Diff location, date stamp variable is defined, along with tools parameters 
$diffLoc   = "ApexSQLDiff"
$stamp = (Get-Date -Format "MMddyyyy_HHMMss") 
$Params = "/pr:""MyProject.axds""    /out:""$outsLoc\SchemaOutput_$stamp.txt"" /sync /v /f" 
$returnCode = $LASTEXITCODE

#initiate the schema comparison and synchronization process
(Invoke-Expression ("& `"" + $diffLoc +"`" " +$Params))

#write output to file
"$outsLoc\SchemaOutput_$dateStamp.txt"

#schema changes are detected
if($returnCode -eq 0)
{
"`r`n $returnCode - Schema changes were successfully synchronized" >> 

}
else
{
#there are no schema changes
if($returnCode -eq 102)
{
"`r`n $returnCode - There are no schema changes. Job aborted" >> 
}
#an error is encountered
else
{
"`r`n $returnCode - An error is encountered" >> 

#output file is opened when an error is encountered
Invoke-Item "$outsLoc\SchemaOutput_$stamp.txt"
}

}

วิธีนี้กำหนดเวลาการเปรียบเทียบระหว่างสองฐานข้อมูลและประสานการเปลี่ยนแปลงที่พบในเวลาจริง นี่คือบทความบางส่วนที่ให้คำแนะนำทีละขั้นตอน:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatically-keep-two-sql-server-database- schemas ในการซิงค์ /

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.