ผลของการมีธุรกรรมเปิดใน MSSQL นานเกินไปคืออะไร?


11

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

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

คำตอบ:


14

การมีธุรกรรมแบบเปิดด้วยตัวเองจะแทบไม่มีผล แบบง่าย ๆ

BEGIN TRANSACTION
-- wait for a while, doing nothing
-- wait a bit longer
COMMIT

จะเลวร้ายที่สุดค้างไว้สองสามไบต์ของค่าสถานะ ไม่ใช่เรื่องใหญ่.

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

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

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

การล็อกโฮลดิ้งใช้ทรัพยากรระบบ นี่คือหน่วยความจำที่ระบบไม่สามารถใช้ในการประมวลผลคำขออื่น ๆ ลดปริมาณงาน

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

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

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

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

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

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


แม้ว่าจะเปิดเป็นเวลาสามวัน?
JanLeeYu

ใช่แม้เป็นเวลาสามวัน จุดสำคัญคือปริมาณงานที่ทำขณะเปิด TX ไม่ใช่แค่เปิดนานเท่าไหร่ แน่นอนในฐานะ DBA คุณอาจต้องการถามเจ้าของธุรกรรมว่าเหตุใดพวกเขาจึงต้องเปิดให้บริการเป็นเวลานาน เมื่อฉันวิ่งทีม DBA ฉันบันทึก TX ทั้งหมดซึ่งเปิดมานานกว่า 30 นาทีและได้สนทนากับเจ้าของ
Michael Green

ตกลง. ขอบคุณสำหรับคำอธิบายที่ดี แม้ว่าทุกคนก็ทำได้ดีเช่นกัน
JanLeeYu

โล่งอก ... ขอบคุณอีกครั้งสำหรับคำตอบ
JanLeeYu

"อัปเดตโค้ดไม่ดี" Yup เห็นนี่ คำแถลงการปรับปรุงภายในลูปที่ไม่ได้มีคุณสมบัติบางชื่อและส่งผลให้เกิดพฤติกรรม 1 = 1 ดังนั้นจึงอัปเดตตารางทั้งหมดสำหรับการวนซ้ำทุกครั้งของลูป (ซึ่งใส่ข้อมูลผิดในแถวเหล่านั้นด้วย
jpmc26

6

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

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


ตัวอย่างเช่นผู้ที่สร้างธุรกรรมถูกตัดการเชื่อมต่อจากเซิร์ฟเวอร์เขา / เธอจะสามารถเข้าสู่ระบบกลับไปที่เซิร์ฟเวอร์อีกครั้งเพื่อปิดการทำธุรกรรมหรือไม่
JanLeeYu

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

ในกรณีที่เกิดขึ้นผู้ดูแลระบบจะยังสามารถปิดธุรกรรมได้หรือไม่
JanLeeYu

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

4

ธุรกรรมที่ไม่สมบูรณ์อาจมีการล็อคจำนวนมากและทำให้เกิดการบล็อค

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

แหล่ง


ตัวอย่างเช่นผู้ที่สร้างธุรกรรมถูกตัดการเชื่อมต่อจากเซิร์ฟเวอร์เขา / เธอจะสามารถเข้าสู่ระบบกลับไปที่เซิร์ฟเวอร์อีกครั้งเพื่อปิดการทำธุรกรรมหรือไม่
JanLeeYu

เมื่อ SQL Server รู้ว่าการเชื่อมต่อขาดหายมันจะย้อนกลับการทำธุรกรรม ดูที่นี่dba.stackexchange.com/questions/47404/… . หากผู้ใช้เดียวกันเชื่อมต่ออีกครั้งมันจะเป็นเซสชั่นที่แตกต่างกันดังนั้นจึงไม่สามารถ "รับ" ธุรกรรมเก่าได้
Michael Green
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.