การย้อนกลับของ SQL Server ทั้งสองนี้แตกต่างกันอย่างไร


13

ใน SQL Server 2008 R2 การย้อนกลับสองแบบนี้แตกต่างกันอย่างไร:

  1. เรียกใช้ALTERคำสั่งสักครู่แล้วกด 'ยกเลิกการดำเนินการ' ใช้เวลาสองสามนาทีในการย้อนกลับอย่างสมบูรณ์

  2. เรียกใช้ALTERคำสั่งเดียวกันแต่ให้แน่ใจว่าLDFไฟล์นั้นไม่ใหญ่พอที่จะทำให้สำเร็จ เมื่อถึงLDFขีด จำกัด และไม่อนุญาตให้ 'autogrowth' การประมวลผลแบบสอบถามจะหยุดทันที (หรือย้อนกลับเกิดขึ้น) พร้อมกับข้อความแสดงข้อผิดพลาดนี้:

The statement has been terminated.
Msg 9002, Level 17, State 4, Line 1
The transaction log for database 'SampleDB' is full. 
To find out why space in the log cannot be reused, see the 
log_reuse_wait_desc column in sys.databases

สองสิ่งนี้แตกต่างกันอย่างไรในประเด็นต่อไปนี้?

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

  2. จะเกิดอะไรขึ้นเมื่อการย้อนกลับครั้งแรกใช้เวลานาน (เป็นเธรดเดี่ยวที่ย้อนกลับ)
    2.1 SQL Server ย้อนกลับและเลิกทำรายการในLDFไฟล์หรือไม่
    2.2 LDFขนาดไฟล์ที่มีขนาดเล็กได้รับในตอนท้ายของการย้อนกลับ (ตั้งแต่DBCC SQLPERF(LOGSPACE))

  3. คำถามเพิ่มเติมหนึ่งข้อ: ระหว่างสถานการณ์ที่สอง SQL Server เริ่มต้นใช้งานLDFไฟล์อย่างรวดเร็ว ในกรณีของฉันมันเพิ่มจากการใช้ 18% เป็น 90% การใช้งานในสองสามนาทีแรก (<4 นาที) แต่เมื่อถึง 99% มันจะอยู่ที่นั่นอีก 8 นาทีในขณะที่การใช้งานที่ผันผวนระหว่าง 99.1% ถึง 99.8% มันเพิ่มขึ้น (99.8%) และลดลง (99.2%) และเพิ่มขึ้นอีกครั้ง (99.7%) และลดลง (99.5%) สองสามครั้งก่อนที่จะเกิดข้อผิดพลาด เกิดอะไรขึ้นเบื้องหลัง?

ลิงก์ใด ๆ ของ MSDN ที่สามารถช่วยอธิบายเรื่องนี้ได้มากยิ่งขึ้น

ตามคำแนะนำของ Ali Razeghi ฉันกำลังเพิ่ม perfmon: Disk Bytes/sec

สถานการณ์ที่ 1:

สถานการณ์ 1

สถานการณ์ที่ 2:

สถานการณ์ที่ 2


เป็นเพียงความคิดเห็นด่วน: ขนาดไฟล์! = พื้นที่ที่ใช้ภายในไฟล์
Aaron Bertrand

@Aaron ใช่ฉันคุ้นเคยกับสิ่งนั้น ฉันใช้ DBCC SQLPERF (LOGSPACE) เพื่อวัดการใช้งาน ไฟล์ LDF ยังคงเหมือนเดิมตลอดระยะเวลาที่ฉัน จำกัด ขนาดไฟล์ไว้ที่ 10 GB การใช้งานภายในแตกต่างกันไป
ToC

1
ฉันสงสัยว่าการย้อนกลับครั้งที่สองจะปรากฏขึ้นทันทีเนื่องจากมีการรายงานข้อผิดพลาดหลังจากการย้อนกลับเสร็จสมบูรณ์ เหล่านี้น่าจะเป็น 8 นาทีที่คุณสังเกตใน 3 ซึ่งการใช้ LDF ยังคงค่อนข้างคงที่
mustaccio

@ustaccio ฉันจะเห็นด้วยกับคุณ แต่สิ่งประดิษฐ์ชี้ไปในทิศทางที่แตกต่างกัน หากในความเป็นจริงการย้อนกลับเกิดขึ้นการใช้งานไฟล์บันทึกจะต้องกลับไปเป็นจำนวนที่น้อยกว่า และไม่อยู่ที่ 99.3% เมื่อมีการโยนข้อความแสดงข้อผิดพลาด
ToC

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

คำตอบ:


1

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

การคาดเดา (ขึ้นอยู่กับการทดสอบบางอย่าง)

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

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

ในสถานการณ์ทั้งสองปริมาณการใช้งานไปยังล็อกไฟล์จะสอดคล้องกัน ดูภาพด้านล่าง:

สถานการณ์ที่ 1:

สถานการณ์ที่ 1:

สถานการณ์ที่ 2:

สถานการณ์ที่ 2

  • สิ่งประดิษฐ์หนึ่งที่เสริมสร้างแนวความคิดนี้คือการจับภาพการติดตามของ SQL ในระหว่างสถานการณ์ทั้งสอง

    • สถานการณ์ที่ 1 มีความชัดเจนในตัวเองเมื่อเรากด 'ยกเลิก' มันจะย้อนกลับ
    • ในสถานการณ์ 2 ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้นหลังจากดำเนินการ 'ย้อนกลับ' โดยปริยาย ใน Sql Trace เราจะเห็นข้อความแสดงข้อผิดพลาด“ บันทึกธุรกรรมสำหรับฐานข้อมูล 'SampleDB' เต็ม” เป็นเวลานานก่อนที่ข้อความจะปรากฏบนหน้าจอ ดังนั้นฉันเดาว่าการย้อนกลับเกิดขึ้นในทั้งสองสถานการณ์ แต่ข้อความแสดงข้อผิดพลาดคือสถานการณ์ 2 ปรากฏขึ้นหลังจากประสบความสำเร็จและดำเนินการย้อนกลับได้อย่างสมบูรณ์
  • สถานการณ์สมมติ 2 ดูเหมือนจะใช้เวลานานขึ้นเนื่องจากดำเนินไปไกลกว่ามากดังนั้นการย้อนกลับใช้เวลานานกว่า

พฤติกรรมที่ไม่ได้อธิบาย:

  • เหตุใดการใช้งานไฟล์บันทึกจึงแตกต่างกันมาก
    • มันเพิ่มขึ้นเป็น 90% จากนั้นลดลงเป็น 85% จากนั้นสูงถึง 99% และวนเวียนอยู่ที่นั่นเป็นเวลานาน ฉันเห็นว่ามันเพิ่มขึ้นหรือลดลงเช่นนี้หลายครั้ง: 99.2%, 99.8%, 99.1%, 99.7% ทำไมสิ่งนี้ถึงเกิดขึ้น
    • คำอธิบายหนึ่งที่เป็นไปได้คืออาจมีกระบวนการพื้นหลัง (เช่น Log Flush) ที่ล้างข้อมูลล็อกทุกสองสามนาที และทุกครั้งที่เริ่มเล่นบางรายการจะถูกล้างออกทำให้มีพื้นที่ว่างมากขึ้น

แนวคิดใด ๆ ที่จะช่วยอธิบายพฤติกรรมนี้ในวิธีที่ดีกว่ายินดี


2
ตรวจสอบกับ Paul Randal เขายืนยันว่าคุณได้ข้อสรุปที่ถูกต้อง - การย้อนกลับเหมือนกันในทั้งสองกรณี
พอลไวท์ 9

0

ฉันลองการทดลองต่อไปนี้และได้ผลลัพธ์ที่คล้ายกัน ในทั้งสองกรณี fn_dblog () แสดงการย้อนกลับที่เกิดขึ้นและดูเหมือนว่าจะเกิดขึ้นเร็วกว่าใน Scenario 2 มากกว่าใน Scenario 1

โดยวิธีการที่ฉันวางทั้ง MDF และ LDF ในดิสก์ภายนอกเดียว (USB 2.0) เดียวกัน

ข้อสรุปเบื้องต้นของฉันคือไม่มีความแตกต่างในการดำเนินการย้อนกลับในกรณีนี้และอาจมีความแตกต่างของความเร็วที่เห็นได้ชัดคือระบบย่อย I / O ที่เกี่ยวข้อง นั่นเป็นเพียงสมมติฐานการทำงานของฉันในขณะนี้

สถานการณ์ที่ 1:

  • สร้างฐานข้อมูลด้วยไฟล์บันทึกที่เริ่มต้นที่ 1MB เติบโตเป็น 4MB และมีขนาดสูงสุด 100MB
  • เปิดธุรกรรมที่ชัดเจนเรียกใช้เป็นเวลา 10 วินาทีแล้วยกเลิกด้วยตนเองภายใน SSMS
  • ดูที่ fn_dblog () นับและบันทึกขนาดสำรองและตรวจสอบ DBCC SQLPERF (LOGSPACE)

สถานการณ์ที่ 2:

  • สร้างฐานข้อมูลด้วยไฟล์บันทึกที่เริ่มต้นที่ 1MB เติบโตเป็น 4MB และมีขนาดสูงสุด 100MB
  • เปิดธุรกรรมที่ชัดเจนเรียกใช้จนกระทั่งบันทึกแสดงข้อผิดพลาดเต็ม
  • ดูที่ fn_dblog () นับและบันทึกขนาดสำรองและตรวจสอบ DBCC SQLPERF (LOGSPACE)

ผลการตรวจสอบประสิทธิภาพ:

สถานการณ์ที่ 1: *** สถานการณ์สมมติ 1 ***

สถานการณ์ที่ 2: *** สถานการณ์ 2

รหัส:

ใช้ [ต้นแบบ];
ไป

IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0
เริ่ม
    แก้ไขฐานข้อมูล [SampleDB] SET SINGLE_USER
        ด้วยการย้อนกลับทันที
    DROP DATABASE [SampleDB];
END;
ไป

สร้างฐานข้อมูล [SampleDB] บนหลัก 
( 
      NAME = N'SampleDB '
    , FILENAME = N'E: \ data \ SampleDB.mdf ' 
    , SIZE = 3MB 
    , FILEGROWTH = 1MB 
)
เข้าสู่ระบบ 
( 
      NAME = N'SampleDB_log '
    , FILENAME = N'E: \ data \ SampleDB_log.ldf '
    , SIZE = 1MB 
    , MAXSIZE = 100MB 
    , FILEGROWTH = 4MB 
);
ไป

ใช้ [SampleDB];
ไป

- เพิ่มโต๊ะ
สร้างตาราง dbo.test
(
    c1 CHAR (8000) ไม่ใช่ NULL DEFAULT REPLICATE ('a', 8000)
) เปิด [หลัก];
ไป

- ตรวจสอบให้แน่ใจว่าเราไม่ได้เป็นแบบจำลองการกู้คืนแบบง่าย ๆ
BACKUP DATABASE SampleDB
TO DISK = 'NUL';
ไป

- สำรองไฟล์บันทึก
BACKUP LOG SampleDB
TO DISK = 'NUL';
ไป

- ตรวจสอบพื้นที่บันทึกที่ใช้
DBCC SQLPERF (LOGSPACE);
ไป

- มีกี่ระเบียนที่มองเห็นได้ด้วย fn_dblog ()
SELECT * จาก fn_dblog (NULL, NULL); - ประมาณ 9 ในกรณีของฉัน

/ **********************************
             สถานการณ์ 1
********************************** /
- เปิดธุรกรรมใหม่แล้วย้อนกลับ
เริ่มต้นการทำธุรกรรม

    INSERT INTO dbo.test ค่าเริ่มต้น;
    GO 10000 - ให้เปิดใช้งานเป็นเวลา 10 วินาทีแล้วกดยกเลิกในหน้าต่างค้นหา SSMS

    - ยกเลิกการทำธุรกรรม
    - ควรใช้เวลาสองสามวินาทีเพื่อเสร็จสิ้น


- ไม่จำเป็นต้องย้อนกลับการทำธุรกรรมเนื่องจากการยกเลิกได้ทำเพื่อคุณแล้ว
-- แค่ลองดู. คุณจะได้รับข้อผิดพลาดนี้
- ข่าวสารเกี่ยวกับ 3903, ระดับ 16, สถานะ 1, บรรทัด 1
- คำขอทำธุรกรรมย้อนกลับไม่มีธุรกรรมเริ่มต้นที่สอดคล้องกัน
ธุรกรรมย้อนกลับ;

- พื้นที่บันทึกที่ใช้คืออะไร สูงกว่า 100%
DBCC SQLPERF (LOGSPACE);
ไป

- มีกี่ระเบียนที่มองเห็นได้ด้วย fn_dblog ()
เลือก * 
จาก fn_dblog (NULL, NULL); - ประมาณ 91,926 ในกรณีของฉัน

- การสำรองบันทึกทั้งหมดแสดงโดย fn_dblog ()?
เลือก SUM ([บันทึกสำรอง]) AS [รวมบันทึกสำรอง]
จาก fn_dblog (NULL, NULL); - ประมาณ 88.72MB


/ **********************************
             สถานการณ์ที่ 2
********************************** /
- ระเบิดฐานข้อมูลและเริ่มต้นใหม่
ใช้ [ต้นแบบ];
ไป

IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0
เริ่ม
    แก้ไขฐานข้อมูล [SampleDB] SET SINGLE_USER
        ด้วยการย้อนกลับทันที
    DROP DATABASE [SampleDB];
END;
ไป

สร้างฐานข้อมูล [SampleDB] บนหลัก 
( 
      NAME = N'SampleDB '
    , FILENAME = N'E: \ data \ SampleDB.mdf ' 
    , SIZE = 3MB 
    , FILEGROWTH = 1MB 
)
เข้าสู่ระบบ 
( 
      NAME = N'SampleDB_log '
    , FILENAME = N'E: \ data \ SampleDB_log.ldf '
    , SIZE = 1MB 
    , MAXSIZE = 100MB 
    , FILEGROWTH = 4MB 
);
ไป

ใช้ [SampleDB];
ไป

- เพิ่มโต๊ะ
สร้างตาราง dbo.test
(
    c1 CHAR (8000) ไม่ใช่ NULL DEFAULT REPLICATE ('a', 8000)
) เปิด [หลัก];
ไป

- ตรวจสอบให้แน่ใจว่าเราไม่ได้เป็นแบบจำลองการกู้คืนแบบง่าย ๆ
BACKUP DATABASE SampleDB
TO DISK = 'NUL';
ไป

- สำรองไฟล์บันทึก
BACKUP LOG SampleDB
TO DISK = 'NUL';
ไป

- ตอนนี้เรามาระเบิดไฟล์บันทึกภายในธุรกรรมของเรา
เริ่มต้นการทำธุรกรรม
    INSERT INTO dbo.test ค่าเริ่มต้น;
    ไป 10,000

- การย้อนกลับไม่เคยเกิดไฟไหม้ ลองมัน. คุณจะได้รับข้อผิดพลาด
- ข่าวสารเกี่ยวกับ 3903, ระดับ 16, สถานะ 1, บรรทัด 1
- คำขอทำธุรกรรมย้อนกลับไม่มีธุรกรรมเริ่มต้นที่สอดคล้องกัน
ธุรกรรมย้อนกลับ;

- ล็อกไฟล์เต็ม 100% หรือไม่ 
DBCC SQLPERF (LOGSPACE);

- มีกี่ระเบียนที่มองเห็นได้ด้วย fn_dblog ()
เลือก * 
จาก fn_dblog (NULL, NULL); - ประมาณ 91,926 ในกรณีของฉัน
ไป

- การสำรองบันทึกทั้งหมดแสดงโดย fn_dblog ()?
เลือก SUM ([บันทึกสำรอง]) AS [รวมบันทึกสำรอง]
จาก fn_dblog (NULL, NULL); - 88.72MB
ไป

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