ตรวจสอบการเปลี่ยนแปลงตาราง SQL Server หรือไม่


142

ฉันจะตรวจสอบฐานข้อมูล SQL Server สำหรับการเปลี่ยนแปลงตารางโดยไม่ต้องใช้ทริกเกอร์หรือปรับเปลี่ยนโครงสร้างของฐานข้อมูลได้อย่างไร? สภาพแวดล้อมการเขียนโปรแกรมที่ฉันต้องการคือ. NETและ C #

ฉันต้องการให้รองรับSQL Server 2000 SP4 หรือใหม่กว่า แอปพลิเคชันของฉันคือการแสดงข้อมูลแบบ bolt-on สำหรับผลิตภัณฑ์ของ บริษัท อื่น ฐานลูกค้าของเราอยู่ในหลักพันดังนั้นฉันไม่ต้องการที่จะใส่ข้อกำหนดที่เราแก้ไขตารางผู้จำหน่ายบุคคลที่สามในทุก ๆ การติดตั้ง

โดย"การเปลี่ยนแปลงตาราง"ฉันหมายถึงการเปลี่ยนแปลงข้อมูลตารางไม่ใช่การเปลี่ยนแปลงโครงสร้างตาราง

ในที่สุดฉันต้องการให้การเปลี่ยนแปลงเกิดขึ้นในแอปพลิเคชันของฉันแทนที่จะต้องตรวจสอบการเปลี่ยนแปลงเป็นระยะ


หลักสูตรที่ดีที่สุดของการดำเนินการให้ความต้องการของฉัน (ไม่ทริกเกอร์หรือสคีแก้ไข, SQL Server 2000 และ 2005) น่าจะเป็นที่จะใช้BINARY_CHECKSUMฟังก์ชั่นในT-SQL วิธีที่ฉันวางแผนที่จะใช้คือ:

ทุกๆ X วินาทีจะเรียกใช้คิวรีต่อไปนี้:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

และเปรียบเทียบกับค่าที่เก็บไว้ หากมีการเปลี่ยนแปลงค่าไปผ่านแถวตารางโดยแถวโดยใช้แบบสอบถาม:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

และเปรียบเทียบเช็คซัมที่ส่งคืนกับค่าที่เก็บไว้


3
พวกเขาไม่ได้ใส่การประทับเวลาที่แก้ไขครั้งล่าสุดลงในแถวของพวกเขาใช่ไหม?
zmbq

สำหรับเร็กคอร์ดถ้าการสนับสนุนเวอร์ชันคือ SQL Server 2005 หรือใหม่กว่า ฉันจะดูที่คุณสมบัตินายหน้าบริการของ SQL Server
Marco Guignard

คำตอบ:


97

ดูคำสั่ง CHECKSUM:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

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

CHECKSUM

นี่คือวิธีที่ฉันใช้เพื่อสร้างการอ้างอิงแคชใหม่เมื่อตารางมีการเปลี่ยนแปลง: การ
อ้างอิงแคชฐานข้อมูล ASP.NET 1.1 (โดยไม่มีทริกเกอร์)


2
Checksums สามารถและจะล้มเหลวในที่สุด หากระบบของคุณยอมรับว่าชุดข้อมูลที่แตกต่างกันสองชุดจะส่งผลให้เกิดผลรวมตรวจสอบเดียวกันกว่าที่คุณคิด สำหรับเหตุผลที่ผมต้องย้ายออกจาก checksums ในส่วนของระบบของเรา ...
LPains

@Lains คุณสามารถอธิบายรายละเอียดเกี่ยวกับงบของคุณได้ไหม?
petrosmm

1
@petrosmm ฉันไม่แน่ใจว่าสิ่งใดที่คุณต้องการให้ฉันทำอย่างละเอียด แต่ฉันจะลอง ลองนึกภาพคุณมีตารางที่มีระเบียนไม่กี่ร้อยรายการคุณสร้างจำนวนเต็มเป็นเช็คซัมบ่อยแค่ไหนที่จะชนกัน ในกรณีของฉันฉันทำอย่างนั้นประมาณ 10 ตารางทั้งหมดมีหลายร้อยรายการ ฉันมีการปะทะกันอย่างน้อยหนึ่งครั้งต่อวัน ตรวจสอบคำตอบอื่น ๆ ของstackoverflow.com/questions/14450415/ นี้
ละเอียด

29

แต่น่าเสียดายที่ CHECKSUM ไม่เคยทำงานอย่างถูกต้องเพื่อตรวจสอบการเปลี่ยนแปลง

มันเป็นเพียงการตรวจสอบดั้งเดิมและไม่มีการคำนวณตรวจสอบซ้ำซ้อน (CRC)

ดังนั้นคุณไม่สามารถใช้มันเพื่อตรวจจับการเปลี่ยนแปลงทั้งหมดเช่นการเปลี่ยนแปลงสมมาตรส่งผลให้ตรวจสอบเดียวกัน!

เช่น. วิธีแก้ปัญหาด้วยCHECKSUM_AGG(BINARY_CHECKSUM(*))จะส่งมอบ 0 สำหรับทั้ง 3 ตารางที่มีเนื้อหาต่างกันเสมอ:


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!


5
นั่นไม่ใช่คำตอบจริงๆมันคือ "ข้อเสนอแนะของคุณใช้งานไม่ได้"
kristianp

1
สิ่งนี้สามารถแก้ไขได้สำหรับข้อมูลที่ซ้ำกันโดยใช้คำหลัก DISINCT ก่อน BINARY_CHECKSUM มีข้อผิดพลาดอื่น ๆ อีกสองสามข้อที่กล่าวถึงที่นี่แต่ไม่ใช่สถานการณ์ทั่วไป
pblack

25

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


20

คุณต้องตรวจสอบการเปลี่ยนแปลงบ่อยแค่ไหนและมีขนาดใหญ่เท่าใด (ในแง่ของขนาดแถว) เป็นตารางในฐานข้อมูลหรือไม่ หากคุณใช้CHECKSUM_AGG(BINARY_CHECKSUM(*))วิธีที่แนะนำโดย John มันจะสแกนทุกแถวของตารางที่ระบุ NOLOCKคำใบ้ช่วย แต่ในฐานข้อมูลขนาดใหญ่คุณจะยังคงกดปุ่มทุกแถว นอกจากนี้คุณยังจะต้องจัดเก็บเช็คซัมสำหรับทุกแถวเพื่อให้คุณบอกว่ามีการเปลี่ยนแปลง

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

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

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


18

น่าเสียดายที่ฉันไม่คิดว่าจะมีวิธีที่สะอาดใน SQL2000 ถ้าคุณจำกัดความต้องการของคุณให้แคบลงไปยัง SQL Server 2005 (และใหม่กว่า) แสดงว่าคุณกำลังทำธุรกิจอยู่ คุณสามารถใช้SQLDependencyคลาสSystem.Data.SqlClientได้ ดูการแจ้งเตือนแบบสอบถามใน SQL Server (ADO.NET)


16

มีงาน DTS (หรืองานที่เริ่มโดยบริการ windows) ที่ทำงานในช่วงเวลาที่กำหนด ทุกครั้งที่รันมันจะได้รับข้อมูลเกี่ยวกับตารางที่กำหนดโดยใช้ระบบINFORMATION_SCHEMAตารางและบันทึกข้อมูลนี้ในที่เก็บข้อมูล เปรียบเทียบข้อมูลที่ส่งคืนเกี่ยวกับโครงสร้างของตารางกับข้อมูลที่ส่งคืนในครั้งก่อนหน้า ถ้ามันแตกต่างคุณก็รู้ว่าโครงสร้างนั้นเปลี่ยนไป

ตัวอย่างแบบสอบถามเพื่อส่งคืนข้อมูลเกี่ยวกับคอลัมน์ทั้งหมดในตาราง ABC (แสดงรายการคอลัมน์จากตาราง INFORMATION_SCHEMA ที่คุณต้องการแทนที่จะใช้ * select ** เหมือนที่ฉันทำที่นี่):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

คุณจะตรวจสอบคอลัมน์ที่แตกต่างกันและมุมมอง INFORMATION_SCHEMA ขึ้นอยู่กับว่าคุณกำหนด "การเปลี่ยนแปลงตาราง" อย่างแน่นอน


2
คำถามเกี่ยวกับการเปลี่ยนแปลงในข้อมูลตารางและ information_schema มีสคีมา (คำจำกัดความคอลัมน์) ของตาราง
เกินไป


6

ตรวจสอบวันที่ส่งมอบล่าสุด ทุกฐานข้อมูลมีประวัติว่าเมื่อใดที่ทำคอมมิทแต่ละครั้ง ฉันเชื่อว่าเป็นมาตรฐานการปฏิบัติตามข้อกำหนดของกรด


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