การสำรองข้อมูลบันทึกธุรกรรมของ SQL Server: ทดสอบว่าบันทึกท้ายดังต่อไปนี้เป็นข้อมูลสำรองบันทึกล่าสุดที่รู้จักหรือไม่


11

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

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

อย่างไรก็ตามฉันไม่ทราบวิธีการตรวจสอบว่าบันทึกท้ายติดตามการสำรองข้อมูลบันทึกล่าสุด

หากฉันมีบันทึกหาง FirstLSN ฉันสามารถเปรียบเทียบกับ LastLSN ของข้อมูลสำรองบันทึกล่าสุดได้ แต่ฉันจะขอรับ FirstLSN ของบันทึกท้ายได้อย่างไร

ฉันต้องการโซลูชันที่ใช้งานได้ตั้งแต่ SQL Server 2005 ขึ้นไป (ควรใช้ t-sql) จนถึงตอนนี้ฉันได้ค้นหา Google ไม่เป็นประโยชน์ Btw ฉันโพสต์สิ่งนี้ใน stackoverflow เป็นครั้งแรก; แต่ย้ายมาที่นี่เนื่องจากถูกตั้งค่าสถานะนอกหัวข้อที่นั่น

แก้ไข

ฉันลองทั้งสองวิธีแก้ปัญหาในตัวอย่างเล็ก ๆ (SQL Server 2005, 9.0.5057):

BACKUP DATABASE TestDb TO DISK = 'C:\temp\backup test\Full.bak' 

-- fire some update queries

BACKUP LOG TestDb TO DISK =  'C:\temp\backup test\Log1.bak' 

-- fire both queries from the provided answers: 
-- Martin Smith's answer yields: 838886656088920652852608
-- Shawn Melton's answer yields: 46000000267600001

RESTORE HEADERONLY FROM DISK = 'C:\temp\backup test\Log1.bak'  
-- yields: 46000000267600001

ดังนั้นจึงปรากฏว่าอันแรกถูกปิดโดยคำสั่งหลายขนาด

ฉันทำแบบทดสอบเดียวกันกับ SQL 2008 SP1 (10.00.2531) ซึ่งทั้งสองแบบสอบถามให้คำตอบที่ถูกต้อง


ฉันค้นคว้ามาแล้วเพราะเป็นคำถามที่น่าสนใจ แต่ฉันไม่ได้ไปไกล ฉันไม่แน่ใจว่า SQL สนับสนุนสิ่งนี้นอกกรอบ
Katherine Villyard

1
ฉันมั่นใจว่ามีวิธีการตรวจสอบนี้อาจใช้ LSN ไม่ใช่วิธีที่จะทำ ฉันจะใส่เงินรางวัลในคำถามในเวลาไม่กี่ชั่วโมงคำถามนี้ต้องมีการดูมากขึ้น ..

คำตอบ:


12

ฉันหันไปใช้สำเนาของSQL Server 2008 Internalsและ DMV sys.database_recovery_statusถูกชี้ให้เห็นเพื่อค้นหา LSN แรกของการสำรองข้อมูลบันทึกครั้งต่อไป คอลัมน์ไหนให้ BOL last_log_backup_lsn:

หมายเลขลำดับการบันทึกของการสำรองข้อมูลบันทึกล่าสุด นี่คือ LSN สุดท้ายของการสำรองข้อมูลบันทึกก่อนหน้าและ LSN เริ่มต้นของการสำรองข้อมูลบันทึกครั้งต่อไป
NULL = ไม่มีการสำรองข้อมูลบันทึกอยู่ ฐานข้อมูลออฟไลน์ไม่เช่นนั้นฐานข้อมูลจะไม่เริ่มทำงาน

เพียงพูดถึงเช่นกันว่า Kalen ยังนำเสนอจุดที่คุณจะได้รับค่า NULL หากฐานข้อมูลอยู่ในโหมดการกู้คืน SIMPLE (โหมด autotruncate) หรือหากไม่มีการสำรองข้อมูลบันทึก

แต่ฉันจะขอรับ FirstLSN ของบันทึกท้ายได้อย่างไร

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

ดังนั้นการดำเนินการต่อไปนี้จะคืนค่าที่ฉันเชื่อว่าคุณกำลังมองหา:


SELECT 
   last_log_backup_lsn
FROM 
   sys.database_recovery_status
WHERE 
   databse_id = DB_ID('MyDb')

DMV นี้พร้อมใช้งานเริ่มต้นใน SQL 2005

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


ผลลัพธ์ของแบบสอบถามนี้ดูเหมือนจะถูกต้อง
Andreas

แน่นอนว่าถูกต้องสำหรับฉัน last_log_backup_lsn เท่ากับ first_lsn ของส่วนท้ายของบันทึก ดังนั้นหากคุณมีไฟล์บันทึกที่จะกู้คืนด้วย last_lsn เท่ากับ last_log_backup_lsn จากรหัสของ Shawn คุณจะรู้ว่าคุณมีการสำรองข้อมูลจนถึงหางบันทึก (แน่นอนว่าจะรับประกันได้จริงในช่วงเวลาของการสอบถามเท่านั้นช่วงเวลาถัดไปที่สามารถเริ่มการสำรองข้อมูลบันทึกใหม่ได้)
RLF

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

6

สิ่งต่อไปนี้ควรทำ

WITH LSN_CTE
AS
(
SELECT TOP 1
       LEFT( LogRecords.[Current LSN], 8 )          AS Part1,
       SUBSTRING( LogRecords.[Current LSN], 10, 8 ) AS Part2,
       RIGHT( LogRecords.[Current LSN], 4 )         AS Part3
FROM   sys.fn_dblog(NULL,NULL) AS LogRecords
ORDER BY [Current LSN]
)
SELECT CAST( CAST( CONVERT( varbinary, Part1, 2 ) AS int ) AS varchar ) +
       RIGHT( '0000000000' + CAST( CAST( CONVERT( varbinary, Part2, 2 ) AS int ) AS varchar ), 10 ) +
       RIGHT( '00000'      + CAST( CAST( CONVERT( varbinary, Part3, 2 ) AS int ) AS varchar ), 5 ) AS [Converted LSN]
FROM   LSN_CTE

ใช้รหัสการแปลงทศนิยมจากบทความนี้

ORDER BY [Current LSN]ดีอาจจะมีค่าใช้จ่ายที่ไม่จำเป็นครบถ้วน ฉันไม่แน่ใจ. ผลลัพธ์ของฟังก์ชันนี้มักจะอยู่ในลำดับ LSN และฉันเดาว่ามันจะอ่านบันทึกตามลำดับ แต่ในกรณี ...


@MartinSmith: fn_dblogดูเหมือนจะไม่ได้รับการบันทึกไว้เป็นอย่างดี ฉันถือว่าผลลัพธ์ของมันเก็บไว้เสมอสำหรับฐานข้อมูลปัจจุบัน (เนื่องจากไม่มีWHERE DbName = 'XXX'ส่วนย่อย)?
Andreas

@Andreas - ใช่มันไม่มีเอกสาร และใช่มันจะส่งคืนข้อมูลจากบันทึกของฐานข้อมูลปัจจุบัน
Martin Smith

ดูการแก้ไขคำถามเดิมของฉัน จำนวนที่ส่งคืนโดยข้อมูลโค้ดของคุณมีขนาดใหญ่กว่า LSN ของการสำรองข้อมูลล่าสุดของฐานข้อมูลเดียวกัน
Andreas

@Andreas - แปลก ฉันลองทดสอบฐานข้อมูลเดียวและทำงานได้อย่างถูกต้อง ไม่แน่ใจว่าข้อผิดพลาดอยู่ที่ไหน คุณใช้ SQL Server เวอร์ชันใดอยู่ CONVERTมีสไตล์พารามิเตอร์2อาจจะมีปัญหา
Martin Smith

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