PostgreSQL ERROR: การยกเลิกคำสั่งเนื่องจากขัดแย้งกับการกู้คืน


159

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

ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed

มีข้อเสนอแนะในการแก้ไขอย่างไร ขอบคุณ


โปรดค้นหาเอกสาร AWS ที่กล่าวถึงข้อผิดพลาดนี้นอกจากนี้ยังมีวิธีแก้ไขด้วยaws.amazon.com/blogs/database/…
arunjos007

คำตอบ:


96

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

การค้นหาที่ยาวขึ้นจะถูกยกเลิกบ่อยขึ้น

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

ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้และวิธีแก้ปัญหาอื่น ๆ มีอธิบายไว้ในส่วนHot Standby - การจัดการข้อขัดแย้งของแบบสอบถามในเอกสาร


11
สำหรับผู้ใช้ PostgreSQL 9.1+: ดูคำตอบของeradmanด้านล่างสำหรับวิธีแก้ปัญหาที่ใช้ได้จริง
Zoltán

5
สำหรับผู้ใช้ PostgreSQL 9.1+: คำตอบของ max-malysh นั้นปลอดภัยกว่ามาก อย่าทำตามคำแนะนำของผู้กำจัดเว้นแต่คุณจะเข้าใจความเสี่ยง
Davos

102

ไม่ต้องสัมผัสhot_standby_feedback. ดังที่คนอื่น ๆ ได้กล่าวไว้การตั้งค่าให้onสามารถขยายต้นแบบได้ ลองนึกภาพการเปิดธุรกรรมบนทาสและไม่ปิดมัน

ให้ตั้งค่าmax_standby_archive_delayและmax_standby_streaming_delayเป็นค่าที่มีเหตุผลแทน:

# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s

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


1
นี่คือทางออกที่เราใช้ ดูเหมือนจะเป็นการประนีประนอมที่ดีที่สุดระหว่างตัวเลือกทั้งหมดที่นำเสนอที่นี่
mohit6up

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

2
นี่ยังคงเป็นทางออกที่ดีที่สุดที่นี่ โปรดทราบว่าใน Redshift คุณสามารถตั้งค่านี้ผ่านการตั้งค่ากลุ่มพารามิเตอร์เฉพาะที่ควรอยู่ในmsนั่นคือ 900s = 16 นาที = 900000ms
NullDev

หากต้องการอัปเดตใน GCP สามารถทำได้ในms cloud.google.com/sql/docs/postgres/…
howMuchCheeseIsTooMuchCheese

1
เรามีการกำหนดค่า (master และ 2 hot standby nodes) และทั้ง 3 โหนดมีการตั้งค่าดังต่อไปนี้ max_standby_archive_delay = 30s , max_standby_streaming_delay = 30s , ** hot_standby_feedback = off ** แต่เราพบข้อผิดพลาดcanceling statement due to conflict with recoveryแม้ในการสืบค้นที่ใช้เวลา 100ms-2000ms ในการดำเนินการ ( ปริมาณงานระหว่างการทดสอบการโหลด ~ 120r / s) เหตุใดจึงมีการยกเลิกการสืบค้นข้อมูลสั้น ๆ บนโหนดสแตนด์บายแม้ว่าจะตั้งค่าการหมดเวลาเป็นเวลา 30 วินาที ... ?
Erikas Neverdauskas

81

ไม่จำเป็นต้องเริ่มการทำธุรกรรมที่ไม่ได้ใช้งานบนหลัก ใน postgresql-9.1 วิธีที่ตรงที่สุดในการแก้ปัญหานี้คือการตั้งค่า

hot_standby_feedback = on

สิ่งนี้จะทำให้ผู้เชี่ยวชาญทราบถึงการสืบค้นที่ใช้เวลานาน จากเอกสาร :

ตัวเลือกแรกคือการตั้งค่าพารามิเตอร์ hot_standby_feedback ซึ่งป้องกันไม่ให้ VACUUM ลบแถวที่เพิ่งตายไปและไม่เกิดความขัดแย้งในการล้างข้อมูล

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


12
ควรตั้งค่าพารามิเตอร์นี้ในโหมดสแตนด์บาย
Steve Kehlet

3
มีข้อเสียบางประการสำหรับมาสเตอร์ในกรณีนี้Hot-Standby-Feedback
Evgeny Liskovets

51

ตามที่ระบุไว้ที่นี่เกี่ยวกับhot_standby_feedback = on:

ข้อเสียของมันคือการสแตนด์บายสามารถขยายต้นแบบได้ซึ่งอาจทำให้บางคนแปลกใจเช่นกัน

และที่นี่ :

max_standby_streaming_delay ใช้การตั้งค่าอะไร ฉันอยากจะตั้งค่าเริ่มต้นให้เป็น -1 แทนที่จะเป็นค่าเริ่มต้น hot_standby_feedback on ด้วยวิธีนี้สิ่งที่คุณทำในโหมดสแตนด์บายจะส่งผลต่อการสแตนด์บายเท่านั้น


ดังนั้นฉันจึงเพิ่ม

max_standby_streaming_delay = -1

และไม่มีpg_dumpข้อผิดพลาดอีกต่อไปสำหรับเราหรือไม่ขยายตัวหลัก :)

สำหรับอินสแตนซ์ AWS RDS โปรดตรวจสอบhttp://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html


1
@lennard สิ่งนี้ใช้ได้กับฉัน ฉันเพิ่มการกำหนดค่านี้ใน postgresql.conf ของทาสจากนั้นรีสตาร์ททาส
อาดีอร่าม

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

7
วิธีตั้งค่านี้บน AWS RDS
Kris MP

1
@KrisMP ใช้ psql
Yehonatan

4
@KrisMP ในกลุ่มพารามิเตอร์ - docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…
r3m0t

14

ข้อมูลตารางบนเซิร์ฟเวอร์ hot standby slave ถูกแก้ไขในขณะที่รันคิวรีที่รันเป็นเวลานาน วิธีแก้ปัญหา (PostgreSQL 9.1+) เพื่อให้แน่ใจว่าไม่มีการแก้ไขข้อมูลตารางคือการระงับการจำลองแบบและดำเนินการต่อหลังจากแบบสอบถาม

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume

1
สิ่งนี้ต้องการสิทธิ์ superuser ดังนั้นอาจไม่ใช่วิธีแก้ปัญหาในบางกรณี
Joao Baltazar

2
ใน PostgreSQL 10 xlogถูกแทนที่ด้วยwalดังนั้นคุณจึงต้องการโทรpg_wal_replay_pause()และpg_wal_replay_resume().
womble

5

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

ดังนั้นเราจึงแก้ปัญหานี้โดยเปิดใช้คุณสมบัติhot_standby_feedbackในคุณสมบัติ Postgres เราอ้างถึงลิงก์ต่อไปนี้

https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/

ฉันหวังว่ามันจะช่วยได้


3

ฉันจะเพิ่มข้อมูลที่อัปเดตและการอ้างอิงถึงคำตอบที่ยอดเยี่ยมของ @ max-malysh ด้านบน

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

  1. ชะลอการใช้แอคชัน WAL สักหน่อยปล่อยให้ Slave ทำธุรกรรมที่ขัดแย้งกันเสร็จแล้วจึงใช้การดำเนินการ
  2. ยกเลิกแบบสอบถามที่ขัดแย้งกันบนทาส

เราเกี่ยวข้องกับ # 1 และสองค่า:

  • max_standby_archive_delay - นี่คือความล่าช้าที่ใช้หลังจากการตัดการเชื่อมต่อระหว่าง master และ slave เป็นเวลานานเมื่อข้อมูลถูกอ่านจากไฟล์เก็บถาวร WAL ซึ่งไม่ใช่ข้อมูลปัจจุบัน
  • max_standby_streaming_delay - ความล่าช้าที่ใช้ในการยกเลิกการสอบถามเมื่อได้รับรายการ WAL ผ่านการจำลองแบบสตรีมมิง

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

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

สำหรับคำอธิบายที่เต็มรูปแบบของวิธีการmax_standby_archive_delayและmax_standby_streaming_delayการทำงานและทำไมไปที่นี่


2

ในทำนองเดียวกันนี่เป็นข้อแม้ประการที่ 2 สำหรับการทำรายละเอียดของ @ Artif3x ของคำตอบที่ยอดเยี่ยมของ @ max-malysh ทั้งสองข้างต้น

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

  • มูลค่าของผู้ติดตามในขณะสแตนด์บาย / สำรองลดน้อยลง
  • คำสั่งอื่น ๆ ที่ทำงานบนสาวกอาจส่งกลับข้อมูลเก่า

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

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

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