การบันทึกทุกการเปลี่ยนแปลงของแถวในฐานข้อมูลนั้นถูกเก็บไว้อย่างไร?


10

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

สิ่งที่คล้ายกันนั้นใช้โดย Stack Exchange เมื่อฉันเปลี่ยนคำถามของคนอื่นมันเป็นไปได้ที่จะพบว่าฉันเปลี่ยนมันและย้อนกลับการเปลี่ยนแปลง

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

  • วัตถุที่มีขนาดค่อนข้างเล็ก: อาจจะมีบางnvarchar(1000)ตัวอย่างเช่น แต่ไม่ blobs ใหญ่ของข้อมูลไบนารีหนึ่งนี้ถูกเก็บไว้โดยตรงบนดิสก์และเข้าถึงได้โดยตรงและไม่ผ่าน Microsoft SQL filestream,
  • โหลดฐานข้อมูลค่อนข้างต่ำและฐานข้อมูลทั้งหมดได้รับการจัดการโดยเครื่องเสมือนหนึ่งเครื่องบนเซิร์ฟเวอร์
  • การเข้าถึงเวอร์ชันก่อนหน้าไม่จำเป็นต้องรวดเร็วเท่ากับการเข้าถึงเวอร์ชันล่าสุด แต่ยังต้องเป็นเวอร์ชันล่าสุดและไม่ช้าเกินไป²

<TL-DR>

ฉันคิดเกี่ยวกับกรณีต่อไปนี้ แต่ฉันไม่มีประสบการณ์จริงกับสถานการณ์เหล่านั้นดังนั้นฉันจะได้ยินความคิดเห็นของผู้อื่น:

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

  2. เก็บเวอร์ชันล่าสุดไว้ในตารางเดียวและในทุก ๆ การเปลี่ยนแปลงให้คัดลอกเวอร์ชันที่ล้าสมัยไปยังตารางอื่นในสคีมาอื่น ข้อบกพร่องคือทุกครั้งที่เราเก็บทุกค่าแม้ว่ามันจะไม่เปลี่ยนแปลง การตั้งค่าการเปลี่ยนแปลงที่จะnullไม่ได้เป็นวิธีการแก้ปัญหาตั้งแต่ฉันยังต้องติดตามเมื่อค่าที่มีการเปลี่ยนแปลงไปหรือจากnullnull

  3. เก็บเวอร์ชันล่าสุดไว้ในตารางเดียวและรายการคุณสมบัติที่เปลี่ยนแปลงด้วยค่าก่อนหน้าในตารางอื่น นี้ดูเหมือนว่ามีสองข้อบกพร่อง: binary(max)หนึ่งที่สำคัญที่สุดคือว่าวิธีเดียวที่จะเรียงลำดับประเภทที่แตกต่างกันของค่าก่อนหน้านี้ในคอลัมน์เดียวกันคือการมี อย่างที่สองคือฉันเชื่อว่ามันจะยากกว่าที่จะใช้โครงสร้างดังกล่าวเมื่อแสดงเวอร์ชันก่อนหน้าแก่ผู้ใช้

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

</ TL-DR>


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

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


3
ที่เกี่ยวข้อง: SQL Server จับเปลี่ยนข้อมูล
Nick Chammas

คำตอบ:


8

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

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

การเปลี่ยนแปลงวันที่สามารถทำได้โดยการทำให้คอลัมน์ datetime ไม่เป็นโมฆะกับการเริ่มต้นของ getdate (); คอลัมน์ผู้ใช้ในการตรวจสอบจะจับผู้ใช้ด้วยคอลัมน์ไม่เป็นค่าเริ่มต้นเป็น Suser_Sname () สมมติว่าผู้ใช้จริงกำลังถูกเลียนแบบในเซสชันนี้จะจับภาพตัวตนของผู้ใช้ที่ทำการเปลี่ยนแปลง

ฐานข้อมูลไม่มีวิธีที่จะทราบถึงที่อยู่ IP ที่เชื่อมต่อกับเว็บเซิร์ฟเวอร์ แอปพลิเคชันจะต้องจับภาพและบันทึกที่อยู่ IP อย่างชัดเจนด้วยธุรกรรม

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

การแก้ปัญหานี้ดีที่สุดด้วยเหตุผลหลายประการ:

  • มันจับการเปลี่ยนแปลงใด ๆ ในตารางไม่เพียง แต่ที่ทำโดยแอปพลิเคชัน

  • สามารถวางตารางการตรวจสอบในชุดดิสก์อื่นเพื่อลดการโหลด I / O บนตารางหลักของคุณ

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

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


คุณพยายามที่จะพูดว่าถ้าฉันมี 1,000 ตารางที่ฉันต้องรักษาบันทึกสำหรับการเปลี่ยนแปลงใด ๆ แล้วฉันต้องสร้าง 1,000 เงาตาราง huh? และ 1,000 ทริกเกอร์สำหรับบันทึกการเปลี่ยนแปลง? ถ้าใช่มันเป็นความคิดที่ผิด ๆ ... เราสามารถสร้างตารางประวัติเดี่ยวและทริกเกอร์เดี่ยวเพื่อจับและบันทึกข้อมูลที่เปลี่ยนแปลง เราสามารถเก็บข้อมูลแถวเก่าและใหม่ในตารางนั้นเป็น xml .... ที่หลายคนทำ .... ฉันชัดเจน !!
โทมัส

1
สำหรับ 1,000 ตารางคุณเขียน utlity ที่อ่านคำจำกัดความจากพจนานุกรมข้อมูลระบบและสร้างทริกเกอร์และคำจำกัดความของตาราง ฉันทำมันบนระบบที่มี 560 ตารางและใช้งานได้ดี
เกี่ยวข้องกับ

0

ฉันรู้ระบบ CMS หลายแห่ง (รวมถึง Wordpress) ที่ใช้ตารางเดียวเพื่อเก็บข้อมูลทุกรุ่น แต่แล้วอีกครั้งพวกเขาจะต้องทำสิ่งนี้สำหรับตารางที่มีการโพสต์บล็อก ดูโครงสร้างฐานข้อมูล Wordpress

นอกจากนี้จำนวนระเบียนและจำนวนการแก้ไขแต่ละแถวจะมีบทบาทสำคัญในการตัดสินใจของคุณ


0

เกี่ยวกับการกำหนดเวอร์ชัน CMS; สำหรับ drupal มันทำตารางพิเศษสำหรับทุกสาขาของเอนทิตีที่เก็บค่าเก่า แนวคิดดังกล่าวช่วยให้คุณสามารถจัดการข้อมูลของคุณได้ดี แต่ฉันคิดว่ามันแพงโซลูชันของฉันคือการแปลงออบเจ็กต์ของฉันให้อยู่ในรูปแบบ xml และเก็บเป็นสตริงด้วยฟิลด์อื่น ๆ (changetime, id ... )

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