ประโยชน์ที่ได้รับจากระดับธุรกรรมการแยกรายการ SET อ่านโดยไม่ได้รับอนุญาต


12

ฉันใช้SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDคำสั่ง SQL ทั่วไปของฉันส่วนใหญ่เพราะนี่เป็นการฝึกฝนให้ฉันเมื่อเริ่มเรียนรู้ภาษา

จากความเข้าใจของฉันระดับแยกนี้ทำหน้าที่เช่นเดียวว่าแต่ฉันเท่านั้นที่เคยมีแนวโน้มที่จะใช้งานWITH (NO LOCK)SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

  • มีเคยเป็นเวลาที่ผมควรจะใช้มากกว่าWITH (NO LOCK)SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
  • ไม่ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDผู้ใช้อื่น ๆ หยุดจากการถูกล็อคออกจากตารางที่ฉันอ่าน?
  • ถ้า SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDใช้เพื่อหยุดล็อค แต่ฉันแค่อ่านข้อมูลจุดประสงค์ในการใช้คืออะไร? มันเป็นเพียงระบบสืบค้นที่เข้มข้นที่จะสร้างล็อค? ควรใช้หรือไม่เมื่อเรียกใช้ข้อความค้นหาที่จะกลับมาพูดอีก 5-10 วินาที?
  • ฉันได้รับแจ้งว่าห้ามใช้ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDเมื่ออ่านข้อมูลที่จะใช้ในการอัปเดตสันนิษฐานว่าเพื่อหลีกเลี่ยงการอัปเดตข้อมูลที่สกปรก นี่เป็นเหตุผลเดียวหรือไม่
  • ด้วยประเภทของฐานข้อมูลที่ฉันกำลังทำงานอยู่มีสภาพแวดล้อมการผลิตและการทดสอบ เราจะไม่ค่อยสอบถามสภาพแวดล้อมการผลิต แต่เมื่อฉันต้องการฉันมักจะใช้SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDในการค้นหาของฉัน ฉันเข้าใจว่าการอ่านที่สกปรกเป็นไปได้ด้วยสิ่งนี้ นอกเหนือจากการรับข้อมูลกลับที่ไม่ได้จบลงด้วยการมุ่งมั่นที่จะฐานข้อมูล (และดังนั้นทิ้งผลลัพธ์ของฉัน) สิ่งที่ 'อ่านสกปรก' ประเภทอื่น ๆ ที่เป็นไปได้?

ขออภัยสำหรับคำถามจำนวนมาก


2
คุณสามารถอ่านข้อมูลเดิมสองครั้งคือหลุมหล่นอีกอัน การใช้ RU หรือ NO LOCK เป็นสิ่งที่ไม่ดี
James Anderson

9
ฉันจะไม่ใช้READ UNCOMMITTEDทุกที่ในแบบเดียวกับที่ฉันจะไม่ใช้WITH (NOLOCK)ทุกที่ (เป็นหลักสิ่งเดียวกัน) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Mark Sinkinson

1
มองไปที่โมเดลการแยก SNAPSHOT พวกเขาแข็งแกร่งกว่า RCU และไม่บล็อกหรือทำให้บล็อก ดูเหมือนว่าเป็นโมเดลเริ่มต้นที่ดีสำหรับคุณ (แทนที่จะเป็น RCU!)
usr

คำตอบ:


26

มันแย่มากที่คุณเรียนรู้แบบนั้น (ขอโทษ!)

READ UNCOMMITTEDให้คุณอ่านทุก ๆ แถวใช่ แม้ผู้ที่ถูกนำมาใช้ในขณะนี้INSERT, UPDATE, DELETEการดำเนินงาน สิ่งนี้มีประโยชน์มากหากคุณต้องการดูข้อมูลบางอย่างหรือในภารกิจสำคัญ - SELECTเงื่อนไขที่บล็อกจะเป็นอันตรายมาก

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

READ UNCOMMITTEDผมจะแนะนำจะลืมเกี่ยวกับ เพียงใช้มันในที่ที่จำเป็นจริงๆ

อีกทางเลือกหนึ่งสำหรับคุณคือการเปิดใช้งานREAD_COMMITTED_SNAPSHOTตัวเลือกฐานข้อมูล - เพื่อให้คุณสามารถใช้READ COMMITTED SNAPSHOTเนื่องจากการกำหนดรุ่นแถวที่เปิดใช้งานใน tempdb ของคุณ วิธีนี้คุณจะอ่านแถว (เวอร์ชันเก่า) อีกแถว สิ่งนี้จะไม่บล็อกข้อความค้นหาของคุณ แต่มันอาจเกิดขึ้นที่คุณอ่านค่าเก่าเช่นกัน แต่เป็นค่าเก่าที่สอดคล้องกัน

ความคิดก็สามารถแทนWITH(READPAST) WITH(NOLOCK)คุณจะอ่านสถานะเดิมของตาราง (เหมือนในSNAPSHOT ISOLATION) แต่คุณจะข้ามแถวที่ถูกล็อกทั้งหมดในปัจจุบันแทน


@ อิออนขอบคุณมากสำหรับการตอบสนอง! ฉันซาบซึ้งในความช่วยเหลือ
dmoney

@HightSight ดูเหมือนว่าจะมี แต่มีโอกาสที่ดีมากที่มันเป็นความหมายของการตีความของฉันขอบคุณทั้งสองวิธีสำหรับการป้อนข้อมูลของคุณ
dmoney

1
SNAPSHOT ISOLATIONREAD COMMITTED SNAPSHOTไม่จำเป็นต้องเปิดใช้งานเพื่อเปิด เฉพาะตัวREAD COMMITTED SNAPSHOTเลือกฐานข้อมูลที่จำเป็นต้องเปิดใช้งานเพื่อให้การกำหนดรุ่นแถวแทนการล็อกเพื่อความสอดคล้องในการอ่านเพื่อหลีกเลี่ยงความจำเป็นในการอ่านที่สกปรก
Dan Guzman

ใช่ฉันหมายความว่า @DanGuzman ขออภัยคำตอบไม่ชัดเจนในจุดนั้น ฉันแก้ไขมัน :-)
Ionic

ด้วย READPAST คุณจะข้ามบันทึกที่ถูกล็อคคุณจะไม่ได้รับค่าเก่าดังนั้นที่เดียวที่ฉันคิดได้ว่ามันสามารถใช้ได้คือการจัดการคิว
James Z

2

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

  1. เมื่อเขียนและทดสอบแพคเกจ SQL Server SSIS ขั้นตอนของแพคเกจอาจถูกห่อในธุรกรรม หากคุณกำลังทดสอบแพ็กเกจโดยการรันทีละขั้นตอนในดีบักเกอร์ SSIS คุณอาจต้องการตรวจสอบตารางขณะที่มีการล็อกบนตาราง การใช้ SET TRANSACTION ISOLATION LEAD READ UNCOMMITTED ช่วยให้คุณใช้ Studio จัดการเซิร์ฟเวอร์ SQL เพื่อตรวจสอบตารางในขณะที่แพคเกจจะถูกดีบั๊ก

  2. ใน SQL Server Manager Studio คุณอาจต้องการทดสอบรหัส T-SQL โดยใส่ไว้ในธุรกรรมเพื่อให้ตัวเลือกในการย้อนกลับการเปลี่ยนแปลง ตัวอย่างเช่นในฐานข้อมูลทดสอบคุณอาจต้องการกู้คืนข้อมูลกลับสู่สถานะเริ่มต้นซึ่งเป็นส่วนหนึ่งของการทดสอบของคุณ หากคุณกำลังทดสอบโค้ดที่ถูกห่อธุรกรรมและคุณต้องการตรวจสอบตารางที่ถูกล็อกในขณะที่ธุรกรรมกำลังดำเนินการอยู่คุณสามารถใช้ SET TRANSACTION ISOLATION LEVEL READ ไม่พร้อมใช้งานเพื่อตรวจสอบค่าในหน้าต่างอื่น

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


1

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

แน่นอนว่าREAD UNCOMMITTED(Dirty Reads) สามารถให้ข้อมูลที่ไม่ถูกต้องในกรณีเหล่านี้ แต่ข้อมูลนั้นถูกต้อง 5 วินาทีก่อนหน้านี้

เวลาที่ Dirty Reads สร้างผลลัพธ์ที่ไม่ดีอย่างแท้จริงคือเมื่อธุรกรรมล้มเหลวและต้องย้อนกลับหรือเมื่อเรียกใช้คิวรีกับสองตารางที่มีการอัปเดตร่วมกันตามปกติโดยใช้ธุรกรรมที่ชัดเจน

ในขณะเดียวกันบนฐานข้อมูลขนาดใหญ่ที่ยุ่งและมีอัตราส่วน 100 (หรือมากกว่า) ต่อ 1 อัตราส่วนของการอ่านเพื่อเขียนการสืบค้นทุกครั้งที่อ่าน (อ่าน) เดียวที่ไม่ได้ใช้ Dirty Reads ทำให้ระบบช้าลงเพราะต้องได้รับและตรวจสอบ สำหรับการล็อคและมันทำให้มีโอกาสมากขึ้นที่การทำธุรกรรมจะล้มเหลว (โดยทั่วไปเกิดจาก Deadlocks) ซึ่งอาจทำให้เกิดปัญหาความสมบูรณ์ของฐานข้อมูลที่ร้ายแรง

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

แน่นอนว่ามีบางครั้งที่ไม่ควรใช้ ฉันไม่ชอบการตั้งค่าฐานข้อมูลให้เป็นค่าเริ่มต้นให้ใช้READ UNCOMMITTEDระดับการแยกหรือแม้แต่ใช้SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDคำสั่งที่ชัดเจนเมื่อเริ่มต้นสคริปต์ SQL และ SPs - มีโอกาสมากเกินไปที่ Dirty Read จะเกิดขึ้นเมื่อไม่ควรใช้ แต่(NOLOCK)คำแนะนำเป็นวิธีที่ดีกว่าเนื่องจากระบุอย่างชัดเจนว่าโปรแกรมเมอร์คิดเกี่ยวกับสิ่งที่พวกเขากำลังทำและตัดสินใจว่าสำหรับตารางเฉพาะในแบบสอบถามเฉพาะนี้ Dirty Reads นั้นปลอดภัย

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

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