การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

บทถอดเสียงคำพูดของ Bruce Momjian ในปี 2020 เรื่อง "การปลดล็อก Postgres Lock Manager"

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

(หมายเหตุ: สามารถรับคำสั่ง SQL ทั้งหมดจากสไลด์ได้จากลิงก์นี้: http://momjian.us/main/writings/pgsql/locking.sql)

สวัสดี! เป็นเรื่องดีที่ได้อยู่ที่นี่ในรัสเซียอีกครั้ง ฉันขอโทษที่ปีที่แล้วมาไม่ได้ แต่ปีนี้ฉันกับอีวานมีแผนใหญ่ ฉันหวังว่าจะอยู่ที่นี่บ่อยขึ้นมาก ฉันชอบมารัสเซีย ฉันจะไปเยี่ยมชม Tyumen, ตเวียร์ ฉันดีใจมากที่ได้เยี่ยมชมเมืองเหล่านี้

ฉันชื่อบรูซ มอมเจียน ฉันทำงานที่ EnterpriseDB และทำงานร่วมกับ Postgres มานานกว่า 23 ปี ฉันอาศัยอยู่ในฟิลาเดลเฟีย สหรัฐอเมริกา ฉันเดินทางประมาณ 90 วันต่อปี และฉันเข้าร่วมการประชุมประมาณ 40 ครั้ง ของฉัน เยี่ยมมากซึ่งมีสไลด์ที่ฉันจะแสดงให้คุณดู ดังนั้นหลังการประชุมคุณสามารถดาวน์โหลดได้จากเว็บไซต์ส่วนตัวของฉัน นอกจากนี้ยังมีการนำเสนอประมาณ 30 รายการ นอกจากนี้ยังมีวิดีโอและรายการบล็อกจำนวนมากมากกว่า 500 รายการ นี่เป็นแหล่งข้อมูลที่ให้ข้อมูลอย่างเป็นธรรม และหากคุณสนใจเนื้อหานี้ฉันขอเชิญคุณใช้มัน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

มาพูดถึงการบล็อคกันดีกว่า

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

คำศัพท์ของเราค่อนข้างซับซ้อน มีกี่คนที่รู้ว่าข้อความนี้มาจากไหน? สองคน. อันนี้มาจากเกม Colossal Cave Adventure ฉันคิดว่ามันเป็นเกมคอมพิวเตอร์แบบข้อความในยุค 80 ที่นั่นคุณต้องเข้าไปในถ้ำ เข้าไปในเขาวงกต และข้อความก็เปลี่ยนไป แต่เนื้อหาก็ประมาณเดิมทุกครั้ง นั่นคือวิธีที่ฉันจำเกมนี้ได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และที่นี่เราเห็นชื่อของล็อคที่มาจาก Oracle เราใช้มัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคำว่า “การเข้าถึง” ก็มีความสำคัญเช่นกัน และคำว่า "แถว" เป็นสตริง นั่นก็คือ การกระจายการเข้าถึง การกระจายแถว

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

โปรดทราบว่าสไลด์จะค่อนข้างเข้าใจยาก ดังนั้นสิ่งที่คุณต้องใส่ใจคือสิ่งที่ไฮไลต์ด้วยสีแดง

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

http://momjian.us/main/writings/pgsql/locking.sql

มาดูกัน. หมายเลขธุรกรรมจะถูกเน้นด้วยสีแดง ฟังก์ชัน SELECT pg_back แสดงอยู่ที่นี่ มันส่งคืนธุรกรรมของฉันและรหัสธุรกรรม

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ในกรณีนี้เราจะเห็นรหัสธุรกรรม นี่คือหมายเลขที่เรามอบหมายให้เธอ และมี ID ธุรกรรมอีกประเภทหนึ่งใน Postgres ซึ่งเรียกว่า ID ธุรกรรมเสมือน

และเราต้องเข้าใจสิ่งนี้ สิ่งนี้สำคัญมาก ไม่เช่นนั้นเราจะไม่สามารถเข้าใจการล็อคใน Postgres ได้

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ดังนั้น หากฉันเรียกใช้คำขอ มันจะแจ้งว่า ID แบ็กเอนด์คือ 2

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และถ้าฉันรันธุรกรรมดังกล่าวเป็นชุด เราจะเห็นว่าตัวนับเพิ่มขึ้นทุกครั้งที่ฉันเรียกใช้แบบสอบถาม ตัวอย่างเช่น เมื่อฉันเรียกใช้แบบสอบถาม 2/10, 2/11, 2/12 เป็นต้น

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

โปรดทราบว่ามีสองคอลัมน์ที่นี่ ทางด้านซ้ายเราจะเห็นรหัสธุรกรรมเสมือน – 2/12 และทางด้านขวาเรามีรหัสธุรกรรมถาวร และช่องนี้ว่างเปล่า และธุรกรรมนี้ไม่ได้แก้ไขฐานข้อมูล ดังนั้นฉันจึงไม่ให้รหัสธุรกรรมถาวรแก่มัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ทันทีที่ฉันรันคำสั่ง analyse ((ANALYZE)) การสืบค้นเดียวกันจะให้ ID ธุรกรรมถาวรแก่ฉัน ดูสิว่าสิ่งนี้เปลี่ยนแปลงไปอย่างไรสำหรับเรา ฉันไม่มี ID นี้มาก่อน แต่ตอนนี้ฉันมีแล้ว

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือคำขออื่น ธุรกรรมอื่น หมายเลขธุรกรรมเสมือนคือ 2/13 และหากฉันขอ ID ธุรกรรมถาวร เมื่อฉันเรียกใช้แบบสอบถาม ฉันจะได้รับมัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ดังนั้นอีกครั้งหนึ่ง เรามีรหัสธุรกรรมเสมือนและรหัสธุรกรรมถาวร เพียงเข้าใจประเด็นนี้เพื่อทำความเข้าใจพฤติกรรมของ Postgres

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ปัญหาอีกประการหนึ่งคือมุมมองนี้กว้างมาก ดังนั้นฉันจึงต้องสร้างอันที่ 2 - lockviewXNUMX

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ดังนั้นเราจึงสร้างตารางชื่อ Lockdemo และเราสร้างหนึ่งบรรทัดที่นั่น นี่คือตารางตัวอย่างของเรา และเราจะสร้างส่วนต่างๆ เพื่อแสดงตัวอย่างการล็อคให้คุณดู

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

หนึ่งแถว หนึ่งคอลัมน์ การล็อคประเภทแรกเรียกว่า ACCESS SHARE นี่เป็นการบล็อกที่มีข้อจำกัดน้อยที่สุด ซึ่งหมายความว่าในทางปฏิบัติแล้วจะไม่ขัดแย้งกับล็อคอื่น ๆ

และหากเราต้องการกำหนดการล็อคอย่างชัดเจน เราก็รันคำสั่ง “lock table” และแน่นอนว่ามันจะบล็อก เช่น ในโหมด ACCESS SHARE เราจะเปิดตารางล็อค และถ้าฉันเรียกใช้ PSQL ในเบื้องหลัง ฉันจะเริ่มเซสชันที่สองจากเซสชันแรกด้วยวิธีนี้ นั่นคือฉันจะทำอะไรที่นี่? ฉันไปที่เซสชั่นอื่นแล้วบอกว่า "แสดงล็อควิวสำหรับคำขอนี้" และที่นี่ฉันมี AccessShareLock ในตารางนี้ นี่คือสิ่งที่ฉันขอ และเขาบอกว่าบล็อกได้รับมอบหมายแล้ว ง่ายมาก.

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นอกจากนี้หากเราดูคอลัมน์ที่สองก็ไม่มีอะไรอยู่ตรงนั้น พวกเขาว่างเปล่า

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และถ้าฉันรันคำสั่ง "SELECT" นี่เป็นวิธีโดยนัย (ชัดเจน) ในการขอ AccessShareLock ดังนั้นฉันจึงปล่อยตารางและเรียกใช้แบบสอบถาม และแบบสอบถามส่งคืนหลายแถว และในบรรทัดใดบรรทัดหนึ่งเราเห็น AccessShareLock ดังนั้น SELECT จึงเรียก AccessShareLock บนโต๊ะ และไม่ขัดแย้งกับสิ่งใดเลยเพราะเป็นการล็อคระดับต่ำ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

จะเกิดอะไรขึ้นถ้าฉันรัน SELECT และมีตารางที่แตกต่างกันสามตาราง? ก่อนหน้านี้ฉันใช้งานเพียงตารางเดียวเท่านั้น ตอนนี้ฉันกำลังใช้งานสามตาราง: pg_class, pg_namespace และ pg_attribute

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และตอนนี้เมื่อฉันดูแบบสอบถาม ฉันเห็น AccessShareLocks 9 รายการในสามตาราง ทำไม ตารางสามตารางถูกเน้นด้วยสีน้ำเงิน: pg_attribute, pg_class, pg_namespace แต่คุณยังสามารถดูได้ว่าดัชนีทั้งหมดที่กำหนดไว้ผ่านตารางเหล่านี้ยังมี AccessShareLock อีกด้วย

และนี่คือล็อคที่ไม่ขัดแย้งกับผู้อื่นในทางปฏิบัติ และสิ่งที่ทำก็แค่ป้องกันไม่ให้เรารีเซ็ตตารางในขณะที่เราเลือก มันสมเหตุสมผล คือถ้าเราเลือกโต๊ะแล้วมันหายไป ณ ขณะนั้น นี่ผิดเลย AccessShare เป็นการล็อคระดับต่ำที่บอกเราว่า "อย่าทำโต๊ะนี้หล่นในขณะที่ฉันทำงาน". โดยพื้นฐานแล้วนั่นคือทั้งหมดที่เธอทำ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ROW SHARE - ล็อคนี้แตกต่างออกไปเล็กน้อย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียนSHARE LOCK ทำอะไรได้บ้าง? เราเห็นว่ารหัสธุรกรรมคือ 681 สำหรับ SELECT และนี่ก็น่าสนใจ เกิดอะไรขึ้นที่นี่? ครั้งแรกที่เราเห็นตัวเลขอยู่ในช่อง “ล็อค” เราใช้รหัสธุรกรรมและแจ้งว่ากำลังบล็อกอยู่ในโหมดพิเศษ สิ่งเดียวที่มันบอกว่าฉันมีแถวที่ถูกล็อคทางเทคนิคไว้ที่ใดที่หนึ่งในตาราง แต่เขาไม่ได้บอกว่าที่ไหนแน่ชัด เราจะดูรายละเอียดเพิ่มเติมในภายหลังเล็กน้อย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ที่นี่เราบอกว่าเราใช้ล็อค

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

SHARE EXCLUSIVE เป็นการล็อคที่ยาวขึ้น

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือคำสั่งตัววิเคราะห์ (ANALYZE) ที่จะใช้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

SHARE LOCK - คุณสามารถล็อคในโหมดแชร์ได้อย่างชัดเจน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

คุณยังสามารถสร้างดัชนีเฉพาะได้อีกด้วย และที่นั่นคุณจะเห็น SHARE LOCK ซึ่งเป็นส่วนหนึ่งของรายการเหล่านั้น และจะล็อคโต๊ะและใส่ SHARE LOCK ไว้ด้วย

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

แบ่งปันแถวพิเศษ - อีกครั้งสามารถตั้งค่าได้อย่างชัดเจน (โดยชัดแจ้ง)

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

หรือเราสามารถสร้างกฎขึ้นมาได้ เช่น ใช้เฉพาะกรณีที่จะใช้กฎนั้น

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

การล็อคแบบพิเศษทำให้ไม่มีใครสามารถเปลี่ยนโต๊ะได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ที่นี่เราจะเห็นล็อคประเภทต่างๆ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ตัวอย่างเช่น ACCESS EXCLUSIVE เป็นคำสั่งบล็อก เช่น ถ้าคุณทำ CLUSTER tableนี่ก็หมายความว่าจะไม่มีใครสามารถเขียนที่นั่นได้ และไม่เพียงล็อคตัวโต๊ะเท่านั้น แต่ยังล็อคดัชนีด้วย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือหน้าที่สองของการบล็อก ACCESS EXCLUSIVE ซึ่งเราจะเห็นได้อย่างแน่ชัดว่าบล็อกอะไรในตาราง มันล็อคแต่ละแถวของตารางซึ่งค่อนข้างน่าสนใจ

นั่นคือข้อมูลพื้นฐานทั้งหมดที่ฉันต้องการให้ เราพูดคุยเกี่ยวกับการล็อค เกี่ยวกับ ID ธุรกรรม เราพูดคุยเกี่ยวกับ ID ธุรกรรมเสมือน เกี่ยวกับ ID ธุรกรรมถาวร

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

ลองดูตัวอย่างที่เฉพาะเจาะจงบางส่วน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

เราจะเริ่มต้นด้วยตารางและหนึ่งแถวในตาราง เมื่อฉันแทรกบางสิ่ง ฉันจะมี ExclusiveLock, Transaction ID และ ExclusiveLock ปรากฏอยู่บนโต๊ะ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

และสิ่งที่สำคัญมากเกี่ยวกับสไลด์นี้ ก็คือมันแสดงให้เห็นอย่างชัดเจนว่า มีระบบอื่นที่ทำงานภายใน MVCC ที่ล็อคแต่ละแถว ดังนั้นเมื่อคุณล็อกแถวนับพันล้านแถว Postgres จะไม่สร้างคำสั่งล็อกแยกกันนับพันล้านคำสั่ง และนี่มีผลดีมากต่อผลผลิต

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

แล้วการบล็อกที่ชัดเจนล่ะ?

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ถ้าฉันคลิกรีเฟรช ฉันล็อคสองแถวไว้ และหากฉันเลือกทั้งหมดแล้วคลิก “อัปเดตทุกที่” ฉันยังคงมีบันทึกการบล็อกอยู่สองรายการ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และเช่นเดียวกัน ถ้าเราแบ่งปัน เราจะทำได้ทั้งหมด 30 ครั้ง

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

เราคืนค่าตารางของเรา ลบทุกอย่าง จากนั้นแทรกหนึ่งแถวอีกครั้ง

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

ฉันจะแสดงตัวอย่างให้คุณดู ฉันจะตัดสินใจเลือกตอนนี้ จากนั้นเราจะทำการ INSERT จากนั้นคุณจะเห็น - 694 คุณสามารถดู ID ของธุรกรรมที่ทำการแทรกนี้ และนั่นคือวิธีการทำงาน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และถ้าฉันดู ID แบ็กเอนด์ของฉันตอนนี้ก็คือ 695

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และฉันเห็น 695 ปรากฏในตารางของฉัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

และคุณจะเห็นได้ว่าที่ด้านบนคือ ShareLock และด้านล่างคือ ExclusiveLock และธุรกรรมทั้งสองก็ได้ผล

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

มารีเซ็ตและดำเนินการอีกครั้งหนึ่ง

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และเพื่อที่จะอธิบายสิ่งนี้ ฉันจะดูตาราง Lockdemo และเราจะดูแถวหนึ่ง. ต่อรายการ 698.

เราได้อัปเดตเป็น 2 แล้ว 699 เป็นการอัพเดตครั้งแรก และสำเร็จหรืออยู่ในรายการรอดำเนินการและรอให้เรายืนยันหรือยกเลิก

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

แต่ลองดูอย่างอื่น - 2/51 เป็นธุรกรรมแรกของเรา ซึ่งเป็นเซสชันแรกของเรา 3/112 เป็นคำขอที่สองที่มาจากด้านบนซึ่งเปลี่ยนค่านั้นเป็น 3 และถ้าคุณสังเกตเห็น คำขอด้านบนจะล็อกตัวเองซึ่งก็คือ 699 แต่ 3/112 ไม่ได้ให้สิทธิ์ล็อก คอลัมน์ Lock_mode บอกว่ากำลังรออะไรอยู่ คาดว่าจะอยู่ที่ 699 และถ้าดูว่า 699 อยู่ตรงไหนก็สูงกว่า และเซสชั่นแรกทำอะไร? เธอสร้างการล็อคพิเศษให้กับ ID ธุรกรรมของเธอเอง นี่คือวิธีที่ Postgres ทำ มันบล็อกรหัสธุรกรรมของตัวเอง และหากคุณต้องการรอให้ใครสักคนยืนยันหรือยกเลิก คุณจะต้องรอในขณะที่มีธุรกรรมที่รอดำเนินการ และด้วยเหตุนี้เราจึงเห็นเส้นแปลกๆ

มาดูกันอีกครั้ง ทางด้านซ้ายเราเห็นรหัสการประมวลผลของเรา ในคอลัมน์ที่สอง เราเห็นรหัสธุรกรรมเสมือนของเรา และคอลัมน์ที่สามเราเห็น lock_type สิ่งนี้หมายความว่า? โดยพื้นฐานแล้วสิ่งที่กล่าวคือกำลังบล็อกรหัสธุรกรรม แต่สังเกตว่าทุกแถวด้านล่างบอกว่ามีความสัมพันธ์กัน ดังนั้นคุณจึงมีตัวล็อคอยู่สองประเภทบนโต๊ะ มีการล็อคความสัมพันธ์ จากนั้นจะมีการบล็อก Transactionid ซึ่งคุณบล็อกด้วยตัวเอง ซึ่งเป็นสิ่งที่เกิดขึ้นในแถวแรกหรือที่ด้านล่างสุด โดยที่ Transactionid อยู่ โดยที่เรารอให้ 699 ดำเนินการให้เสร็จสิ้น

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และใน lock_type สิ่งอันดับคุณจะเห็นตัวเลข

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

คุณจะเห็นว่ามันคือ 0/10. และนี่คือเลขหน้า, และออฟเซ็ตของแถวนี้ด้วย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคุณจะเห็นว่ามันกลายเป็น 0/11 เมื่อเราอัปเดต

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

แต่ในความเป็นจริงมันเป็น 0/10 เพราะต้องรอการดำเนินการนี้ เรามีโอกาสได้เห็นว่านี่คือซีรีย์ที่ฉันรอคอนเฟิร์ม

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือมุมมองแบบเรียกซ้ำที่มีส่วนอื่นด้วย แล้วมันก็นำทุกอย่างกลับมารวมกันอีกครั้ง ลองใช้สิ่งนี้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

จะเกิดอะไรขึ้นถ้าเราทำการอัปเดตพร้อมกันสามครั้งและบอกว่าแถวตอนนี้เป็นสามรายการแล้ว และเราจะเปลี่ยน 3 เป็น 4.

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และที่นี่เราเห็น 4. และรหัสธุรกรรม 702

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

จากนั้นฉันจะเปลี่ยน 4 เป็น 5 และ 5 เป็น 6 และ 6 เป็น 7 และฉันจะจัดแถวคนจำนวนหนึ่งที่จะรอให้ธุรกรรมนี้จบลง

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และทุกอย่างก็ชัดเจน แถวแรกคืออะไร? นี่คือ 702 นี่คือรหัสธุรกรรมที่ตั้งค่านี้แต่เดิม คอลัมน์ Granted ของฉันเขียนว่าอะไร ฉันมีเครื่องหมาย f. นี่คือการอัปเดตของฉันที่ไม่สามารถอนุมัติ (5, 6, 7) ได้เนื่องจากเรากำลังรอให้ ID ธุรกรรม 702 สิ้นสุด ที่นั่นเรามีการบล็อก ID ธุรกรรม และส่งผลให้มีการล็อค ID ธุรกรรม 5 รายการ

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือสิ่งที่ดูเหมือน ชัดเจนว่าพวกเขากำลังรอบรรทัดที่ 12 ทั้งหมด

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือสิ่งที่เราเห็นที่นี่ นี่คือ 0/12.

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และตอนนี้เราจะติดตั้งการหยุดชะงักสองครั้ง เราจะใส่ 50 และ 80 ในแถวแรก ฉันจะอัปเดตจาก 50 เป็น 50 ฉันจะได้หมายเลขธุรกรรม 710

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

จากนั้นฉันจะเปลี่ยน 80 เป็น 81 และ 50 เป็น 51

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และยังบอกด้วยว่าแถวใดเกิดการหยุดชะงัก และนี่คือจุดที่มันเริ่มแปลก

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ตอนนี้เรากำลังอัปเดต 80 ถึง 80

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และนี่คือจุดเริ่มต้นของการหยุดชะงัก 710 กำลังรอการตอบกลับจาก 711 และ 711 กำลังรอ 710 และเรื่องนี้จะไม่จบลงด้วยดี และไม่มีทางออกไปจากเรื่องนี้ได้ และจะคาดหวังคำตอบจากกันและกัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และมันจะเริ่มชะลอทุกอย่าง และเราไม่ต้องการสิ่งนั้น

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

มีการหยุดชะงักสามทางหรือไม่? เป็นไปได้ไหม? ใช่.

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

เราป้อนตัวเลขเหล่านี้ลงในตาราง เราเปลี่ยน 40 เป็น 40 เราทำการบล็อก

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

เราเปลี่ยน 60 เป็น 61, 80 เป็น 81

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

แล้วเราก็เปลี่ยน 80 แล้วก็บูม!

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และตอนนี้ 714 กำลังรอ 715 716 กำลังรอ 715 และไม่มีอะไรสามารถทำได้เกี่ยวกับเรื่องนี้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ปัญหาต่อไปคือทำให้เป็นอนุกรมได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

หากมีการล็อคแบบอนุกรมแบบพิเศษ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และเรากลับมาที่ 719 ผลลัพธ์ของมันค่อนข้างปกติ

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคุณสามารถคลิกเพื่อทำธุรกรรมจากซีเรียลไลซ์ได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคุณตระหนักได้ว่าตอนนี้คุณมีล็อค SA ประเภทอื่นแล้ว ซึ่งก็คือทำให้สามารถซีเรียลไลซ์ได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ดังนั้นเราจึงมีการล็อครูปแบบใหม่ที่เรียกว่า SARieadLock ซึ่งเป็นการล็อคแบบซีเรียลและให้คุณป้อนซีเรียลได้

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคุณยังสามารถแทรกดัชนีเฉพาะได้อีกด้วย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ในตารางนี้เรามีดัชนีที่ไม่ซ้ำกัน

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

ถ้าผมใส่เลข 2 ตรงนี้ ผมก็มี 2 แต่ด้านบนสุด ผมใส่อีก 2 เข้าไป และคุณจะเห็นว่า 721 มีตัวล็อคพิเศษ แต่ตอนนี้ 722 กำลังรอให้ 721 ดำเนินการให้เสร็จสิ้น เนื่องจากไม่สามารถแทรก 2 ได้จนกว่าจะรู้ว่าจะเกิดอะไรขึ้นกับ 721

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และถ้าเราทำธุรกรรมย่อย

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

เรามี 723.

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และถ้าเราบันทึกจุดแล้วอัปเดต เราก็จะได้รับรหัสธุรกรรมใหม่ นี่เป็นพฤติกรรมอีกรูปแบบหนึ่งที่คุณต้องระวัง หากเราส่งคืนสิ่งนี้ ID ธุรกรรมจะหายไป 724 กำลังออกเดินทาง แต่ตอนนี้เรามี 725.

แล้วฉันกำลังพยายามทำอะไรที่นี่? ฉันกำลังพยายามแสดงตัวอย่างการล็อคที่ผิดปกติที่คุณอาจพบ: ไม่ว่าจะเป็นการล็อคแบบอนุกรมหรือ SAVEPOINT การล็อคเหล่านี้เป็นประเภทต่างๆ ที่จะปรากฏในตารางการล็อค

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

นี่คือการสร้างการล็อคที่ชัดเจน (ชัดเจน) ซึ่งมี pg_advisory_lock

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคุณเห็นว่าประเภทการบล็อกแสดงเป็นคำแนะนำ และในที่นี้เขียนว่า "ที่ปรึกษา" ด้วยสีแดง และคุณสามารถบล็อกแบบนี้ไปพร้อม ๆ กันด้วย pg_advisory_unlock

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และที่นี่เราสร้าง pg_stat_view

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

คุณสมบัติที่มีประโยชน์อีกอย่างหนึ่งก็คือ pg_blocking_pids. คุณอาจไม่เคยได้ยินเกี่ยวกับเธอ เธอกำลังทำอะไรอยู่? ช่วยให้เราสามารถบอกได้ว่าสำหรับเซสชันนี้ 11740 รหัสกระบวนการใดที่รออยู่ และคุณจะเห็นว่า 11740 กำลังรอ 724 และ 724 อยู่ด้านบนสุด และ 11306 คือรหัสกระบวนการของคุณ โดยพื้นฐานแล้ว ฟังก์ชันนี้จะผ่านตารางล็อคของคุณ และฉันรู้ว่ามันซับซ้อนนิดหน่อย แต่คุณก็เข้าใจมันได้ โดยพื้นฐานแล้วฟังก์ชันนี้จะผ่านตารางล็อคนี้และพยายามค้นหาว่า ID กระบวนการนี้ได้รับการล็อคที่รออยู่จากที่ใด และยังพยายามค้นหาว่ากระบวนการใดที่รอการล็อคนั้นมี ID กระบวนการใด ดังนั้นคุณจึงสามารถรันฟังก์ชันนี้ได้ pg_blocking_pids.

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

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

คำถาม:

ตัวอย่างเช่น หากฉันพยายามอัปเดตแถว และเซสชันที่สองพยายามลบทั้งตาราง เท่าที่ผมเข้าใจน่าจะมีอะไรบางอย่างเหมือนกับการล็อคเจตนา มีสิ่งนี้ใน Postgres หรือไม่?

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

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

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

นี่จะดูเหมือนล็อคเอกสิทธิ์ใช่ไหม?

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

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

เราต้องทำอะไรเพื่อหลีกเลี่ยงสถานการณ์การหยุดชะงักเมื่อเรามีเซสชันจำนวนมากและมีผู้ใช้จำนวนมาก

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

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

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

เป็นไปได้ไหมที่จะเพิ่มการหมดเวลาการล็อคให้กับ Postgres ตัวอย่างเช่น ใน Oracle ฉันสามารถเขียนว่า "select to update" และรอ 50 วินาทีก่อนที่จะอัปเดต มันดีสำหรับการสมัคร แต่ใน Postgres ฉันต้องทำทันทีและไม่รอเลย หรือรอจนกว่าจะถึงเวลาหนึ่ง

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

คุณสามารถเปิดสไลด์ 75 ได้หรือไม่?

ใช่

การปลดล็อค Postgres Lock Manager บรูซ มอมเจียน

และคำถามของฉันมีดังต่อไปนี้ เหตุใดกระบวนการอัปเดตทั้งสองจึงคาดหวัง 703

และนี่เป็นคำถามที่ดี ฉันไม่เข้าใจว่าทำไม Postgres ถึงทำเช่นนี้ แต่เมื่อ 703 ถูกสร้างขึ้น ก็คาดว่าจะมี 702 และเมื่อ 704 และ 705 ปรากฏขึ้น ดูเหมือนว่าพวกเขาไม่รู้ว่าตนกำลังคาดหวังอะไรอยู่ เพราะยังไม่มีสิ่งใดอยู่ที่นั่น และ Postgres ทำเช่นนี้: เมื่อคุณไม่สามารถล็อคได้ มันจะเขียนว่า "มีประโยชน์อะไรในการประมวลผลคุณ" เพราะคุณกำลังรอใครบางคนอยู่แล้ว ดังนั้นเราจะปล่อยให้มันค้างอยู่ในอากาศ มันจะไม่อัปเดตเลย แต่เกิดอะไรขึ้นที่นี่? ทันทีที่ 702 เสร็จสิ้นกระบวนการและ 703 ได้รับการล็อค ระบบก็กลับมา แล้วเธอก็บอกว่าตอนนี้มีคนรออยู่สองคน แล้วมาอัพเดตไปพร้อมๆ กันนะครับ และให้เราระบุว่าทั้งคู่กำลังคาดหวัง

ฉันไม่รู้ว่าทำไม Postgres ถึงทำเช่นนี้ แต่มีปัญหาที่เรียกว่า f…. สำหรับฉันดูเหมือนว่านี่ไม่ใช่คำในภาษารัสเซีย นี่คือช่วงเวลาที่ทุกคนกำลังรอปราสาทแห่งเดียว แม้ว่าจะมีเจ้าหน้าที่ 20 คนที่รอปราสาทอยู่ก็ตาม และทันใดนั้นพวกเขาทั้งหมดก็ตื่นขึ้นพร้อมกัน และทุกคนก็เริ่มพยายามโต้ตอบ แต่ระบบทำให้ทุกคนรอ 703 อยู่ เพราะทุกคนรออยู่และเราจะจัดแถวให้ทั้งหมดทันที และหากมีคำขอใหม่อื่นใดปรากฏขึ้นหลังจากนี้ เช่น 707 ก็จะมีความว่างเปล่าอีกครั้ง

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

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

สำหรับฉันดูเหมือนว่ามันจะสมเหตุสมผลกว่ามากเมื่อ 705 คาดหวัง 704

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

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

มี บทความเกี่ยวกับล็อคโดย Egor Rogov. ดูสิพวกมันน่าสนใจและมีประโยชน์ด้วย แน่นอนว่าหัวข้อนี้ซับซ้อนมาก ขอบคุณมากบรูซ!

ที่มา: will.com

เพิ่มความคิดเห็น