เวลาแฝงของเครือข่ายที่เพิ่มขึ้นจะทำให้ตารางล็อคใน MS SQL Server หรือไม่


16

ถ้าฉันโทรไปยังฐานข้อมูล SQL Server เพียงครั้งเดียวผ่านเครือข่ายเวลาแฝงที่สูงตารางจะล็อกเกิดขึ้นเนื่องจากเวลาแฝงนั้นหรือไม่ สมมติว่าฉันสืบค้นตาราง A สำหรับระเบียนบางรายการและ SQL Server ต้องส่งคืนข้อมูลนั้นผ่านเครือข่ายที่ช้า - จะมีการล็อกการอ่านบนตาราง A ในขณะที่เซิร์ฟเวอร์ส่งการตอบสนองผ่านเครือข่ายหรือ SQL Server ปล่อยการล็อกก่อนส่ง การตอบสนอง?

นอกจากนี้คำตอบจะแตกต่างกันไปตามขนาดของการตอบสนองหรือไม่? ถ้ามันต้องคืน KB สองสามเทียบกับหลายร้อย MB นั่นจะสร้างความแตกต่างได้หรือไม่?

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


เว้นแต่คุณจะระบุnolockคำใบ้จะมีการล็อคเสมอ เวลาในการตอบสนองจะเป็นตัวกำหนดระยะเวลาของการล็อค
Brandon

3
และแม้จะมีnolock, คุณยังจะได้รับล็อค
billinkc

@brandon นั่นเป็นเอกสารจาก Microsoft ทุกที่หรือไม่? การค้นหาของฉันว่างเปล่า
Evan M

1
@Brandon NOLOCK ไม่ได้หมายความว่าคุณคิดว่ามันหมายถึงอะไร
Aaron Bertrand

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- นี่หมายถึงถ้าคุณใช้ nolock อาจไม่มีการล็อค ฉันแค่ชี้แจง
Aaron Bertrand

คำตอบ:


15

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

มันไม่ถูกต้องมันขึ้นอยู่กับระดับการแยก

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

ถ้าคุณไม่มีประเภท LOB

ประเภท LOB ซึ่งมีขนาดใหญ่มากอาจไม่สามารถบัฟเฟอร์ได้ ล็อคที่ใช้ร่วมกันจะต้องมีการซื้อและถือจนเสร็จสมบูรณ์คำสั่งเป็นหลักให้คุณพฤติกรรมที่REPEATABLE READREAD COMMITTED

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

เวลาแฝงไม่ได้ทำให้ล็อคตารางไม่ อย่างไรก็ตามหากล็อคตารางได้รับความหน่วงแฝงจะยืดออก

หากต้องการอ้างถึงคนที่รู้จักกลไกของสิ่งนี้ดีกว่าฉัน ( @RemusRusanu ):

ผลลัพธ์จะถูกส่งกลับไปยังโปรแกรมไคลเอนต์เมื่อการดำเนินการดำเนินการ ในฐานะที่เป็น 'ฟอง' แถวของต้นไม้การดำเนินงานผู้ประกอบการด้านบนมักจะได้รับมอบหมายด้วยการเขียนแถวเหล่านี้ลงในบัฟเฟอร์เครือข่ายและส่งพวกเขากลับไปยังลูกค้า ผลลัพธ์จะไม่ถูกสร้างขึ้นในที่เก็บข้อมูลระดับกลาง (หน่วยความจำหรือดิสก์) ก่อนแล้วจึงส่งกลับไปยังไคลเอนต์ แต่จะถูกส่งกลับไปตามที่สร้างขึ้น แน่นอนว่าการส่งผลลัพธ์กลับไปยังไคลเอนต์นั้นขึ้นอยู่กับโปรโตคอลควบคุมการไหลของเครือข่าย หากลูกค้าไม่ได้ใช้ผลลัพธ์อย่างแข็งขัน (เช่นการเรียก SqlDataReader.Read ()) ในที่สุดการควบคุมการไหลจะต้องปิดกั้นด้านการส่ง (แบบสอบถามที่กำลังดำเนินการ) และสิ่งนี้จะระงับการดำเนินการของ สอบถาม[แหล่ง]

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


9

คำตอบของมาร์คช่วยขจัดความสับสนมากมาย แต่ฉันต้องการโพสต์สิ่งที่ฉันค้นพบหลังจากที่ฉันทดสอบโดยใช้ NetBalancer เพื่อเลียนแบบความล่าช้า

ฉันมีเครื่องท้องถิ่นของฉันเรียกเซิร์ฟเวอร์ SQL ระยะไกลและดำเนินการทั้ง SELECT และ INSERT บนโต๊ะภายในธุรกรรมขนาดเล็ก บนเครื่องรีโมตฉันเชื่อมต่อกับอินสแตนซ์ SQL ในเครื่องและใช้ลูป WHILE เพื่อวนซ้ำบนตาราง sys.dm_tran_locks ซ้ำ ๆ เพื่อค้นหาการล็อกใด ๆ บนตารางที่ฉันแก้ไขและอ่าน ฉันติดตั้ง NetBalancer บนเซิร์ฟเวอร์และใช้เพื่อจำลองเวลาแฝงของเครือข่ายในการเชื่อมต่อเครือข่ายของเซิร์ฟเวอร์

นี่คือสิ่งที่ฉันพบ:

  • สำหรับข้อความที่ไม่ส่งคืนข้อมูลจำนวนมากไปยังไคลเอนต์เวลาในการตอบสนองจะไม่มีผลต่อการล็อก ฉันได้รับข้อมูลกลับมาเพียงไม่กี่ร้อยไบต์เท่านั้น ธุรกรรมบนเครื่องของฉันมี WAITFOR 250 มิลลิวินาทีซึ่งเก็บล็อคไว้และเมื่อฉันเพิ่มเวลาแฝงของเครือข่ายเป็น 5,000 มิลลิวินาทีระยะเวลาล็อคจะอยู่ใกล้กับ 250 มิลลิวินาที
  • สำหรับคำสั่งที่ส่งคืนข้อมูลจำนวนมากความหน่วงแฝงส่งผลต่อการล็อกอย่างแน่นอนฉันส่งคืนแถวจำนวนหมื่นกลับไปที่ไคลเอ็นต์และไม่มีเวลาแฝงระยะเวลาล็อคสั้น เมื่อฉันเพิ่มเวลาแฝงล็อคจะดำเนินต่อไปจนกระทั่งฉันได้รับข้อมูลทั้งหมด

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


ผลลัพธ์ที่น่าสนใจ มีโปรแกรม / ไลบรารีไคลเอ็นต์ใดบ้าง
James L

สิ่งที่ดี. โอกาสใดที่คุณสามารถใช้เวลาเพิ่มขึ้นเล็กน้อยและดูว่าคุณสามารถกำหนดขนาดผลลัพธ์ที่เกิดขึ้นได้ไหม
Mark Storey-Smith

@ MarkStorey-Smith ฉันไม่คิดว่าฉันจะได้รับค่าที่แม่นยำและมันจะแตกต่างกันไปตามเครื่องจักร จากvircom.com/security/improve-sql-nic-performanceดูเหมือนว่าเป็นการตั้งค่าของ NIC ในท้องถิ่นของคุณและตั้งค่าบนเซิร์ฟเวอร์ฐานข้อมูลของฉันเป็น 'อัตโนมัติ'
Evan M

@ James ฉันเพิ่งใช้ SSMS กับทั้งสองเครื่อง
Evan M

0

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

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

แก้ไข: Evan คุณสามารถอ้างถึงบทความการสนับสนุน MS นี้

ในส่วนที่ 3

การปิดกั้นที่เกิดจาก SPID ที่แอปพลิเคชันไคลเอนต์ที่สอดคล้องกันไม่สามารถเรียกผลลัพธ์ทั้งหมดไปสู่การเสร็จสิ้น

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


ขอบคุณสำหรับคำตอบของคุณ Shanky! คุณรู้ไหมว่าเอกสารนี้ถูกบันทึกไว้ทุกที่หรือไม่?
Evan M


5
สิ่งนี้ไม่ถูกต้อง
Mark Storey-Smith

นี่ถูกต้องดูเหมือนว่า 'แอปพลิเคชันไม่สามารถดึงข้อมูลแถวผลลัพธ์ทั้งหมดสามารถล็อกได้บนตารางบล็อกผู้ใช้รายอื่น หากคุณกำลังใช้แอปพลิเคชันที่ส่งคำสั่ง SQL ไปยังเซิร์ฟเวอร์อย่างโปร่งใสแอปพลิเคชันต้องดึงข้อมูลแถวผลลัพธ์ทั้งหมด หากไม่ใช่ (และหากไม่สามารถกำหนดค่าให้ทำเช่นนั้นได้) คุณอาจไม่สามารถแก้ไขปัญหาการบล็อกได้ เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถ จำกัด แอปพลิเคชันที่มีพฤติกรรมไม่ดีให้กับการรายงานหรือฐานข้อมูลสนับสนุนการตัดสินใจ ' มากกว่าที่ฉันพูดในแง่ทั่วไป คุณสามารถอ่านได้จากที่นี่support2.microsoft.com/kb/224453
Shanky

4
@Shanky สร้างตารางขนาดใหญ่ SELECT *จากที่ในที่READ COMMITTEDหนึ่งการเชื่อมต่อ SSMS ตรวจสอบล็อคจากที่อื่น ทุกครั้งที่คุณเห็นมีล็อคกี่อัน?
Mark Storey-Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.