มีการหมดเวลาสำหรับการเชื่อมต่อ PostgreSQL ที่ไม่ได้ใช้งานหรือไม่


98
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                 
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle             

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


คุณเชื่อมต่อกับ DB อย่างไร socketTimeout อาจเป็นสิ่งที่คุณกำลังมองหา
ล่าง

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


@ user1012451 เมื่อคุณพูดว่า "ปิดแต่ละรายการที่ไม่ได้ใช้งาน" คุณหมายถึงยุติ<IDLE> in transactionเซสชันโดยปล่อยให้เซสชันทำงาน แต่อยู่ใน<IDLE>สถานะใช่หรือไม่ กล่าวอีกนัยหนึ่งคือยุติการทำธุรกรรม แต่ไม่ใช่เซสชัน? (โหวตลง: คำถามไม่ชัดเจน)
Craig Ringer

@CraigRinger หลังจากนั้นไม่นานเราถึงการเชื่อมต่อไคลเอนต์สูงสุด ในการแก้ปัญหานั้นเราต้องรีสตาร์ทเว็บแอปซึ่งบังคับให้รีสตาร์ท postgresql ด้วย ซึ่งจะล้างทุกการเชื่อมต่อ เมื่อเราเห็นสิ่งเหล่านี้idleตลอดไปเราจะถามว่าเราสามารถกำหนดระยะหมดเวลาสำหรับการเชื่อมต่อ / เซสชันแต่ละครั้งได้หรือไม่ (ฉันไม่รู้คำศัพท์ที่ถูกต้องขออภัย) หากการทำธุรกรรมที่ใช้เวลา 5 นาทีสำหรับบางสิ่งบางอย่าง app เว็บปกติต้องผิด ....
user1012451

คำตอบ:


120

ดูเหมือนว่าคุณมีการเชื่อมต่อรั่วไหลในแอปพลิเคชันของคุณเนื่องจากไม่สามารถปิดการเชื่อมต่อร่วมกันได้ คุณไม่ได้มีปัญหาเฉพาะกับ<idle> in transactionเซสชัน แต่มีการเชื่อมต่อโดยรวมมากเกินไป

การฆ่าการเชื่อมต่อไม่ใช่คำตอบที่ถูกต้อง แต่เป็นวิธีแก้ปัญหาชั่วคราวที่ใช้ได้

แทนที่จะเริ่ม PostgreSQL ใหม่เพื่อบูตการเชื่อมต่ออื่น ๆ ทั้งหมดจากฐานข้อมูล PostgreSQL โปรดดู: ฉันจะแยกผู้ใช้รายอื่นทั้งหมดออกจากฐานข้อมูล postgres ได้อย่างไร และจะวางฐานข้อมูล PostgreSQL ได้อย่างไรหากมีการเชื่อมต่อที่ใช้งานอยู่ . ส่วนหลังแสดงข้อความค้นหาที่ดีกว่า

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

keepalive TCPจะไม่ทำงานที่นี่เพราะ app จะยังคงเชื่อมต่อและมีชีวิตอยู่มันก็ไม่ควรจะเป็น

ใน PostgreSQL 9.2 ขึ้นไปคุณสามารถใช้state_changeคอลัมน์การประทับเวลาใหม่และstateฟิลด์pg_stat_activityเพื่อใช้ Reaper การเชื่อมต่อที่ไม่ได้ใช้งาน ให้งาน cron ดำเนินการดังนี้:

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < current_timestamp - INTERVAL '5' MINUTE;

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


4
ดี แต่มันจะฆ่าแบ็กเอนด์ PgAdmin อื่น ๆ ใช้เงื่อนไขเพิ่มเติม application_name = ''
Andrew Selivanov

1
ฉันสามารถเรียกใช้ pg_terminate_backend ได้หรือไม่หากฉันใช้ pgbouncer
Henley Chiu

@HenleyChiu ฉันไม่เห็นว่าทำไมไม่แม้ว่าฉันจะไม่ได้ตรวจสอบโดยเฉพาะ
Craig Ringer

1
การดำเนินการนี้ดูเหมือนจะฆ่ากระบวนการส่ง WAL ของฉัน
โจเซฟเพอร์ซี่

@CraigRinger แม้แต่การเชื่อมต่อ psql ก็ถือว่าเป็นการเชื่อมต่อที่ไม่ได้ใช้งาน และเหตุใดจึงต้องปิดการเชื่อมต่อที่ไม่ได้ใช้งานตั้งแต่แรก ฉันมีโค้ดที่รันมานานซึ่งสร้างการเชื่อมต่อกับ pg ทำการดำเนินการ dml บางอย่างจากนั้นรอข้อความผ่านคิวจากนั้นดำเนินการ dml เพิ่มเติมตอนนี้ในช่วงเวลานั้นคือในขณะที่รอคิว (สำหรับข้อความ) ตามที่กล่าวไว้ข้างต้น แม้แล้วการเชื่อมต่อกับ postges idleคือ ทำไมฉันต้องปิด
Viren

73

ใน PostgreSQL 9.6 มีตัวเลือกใหม่idle_in_transaction_session_timeoutที่ควรบรรลุตามที่คุณอธิบาย คุณสามารถตั้งค่าได้โดยใช้SETคำสั่งเช่น:

SET SESSION idle_in_transaction_session_timeout = '5min';

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

อะไรแบบนี้ใน PostgreSQL เวอร์ชันก่อน ๆ ??
sdsc81

ไม่จำเป็นต้องมีบางอย่างที่คล้ายกับคำตอบอื่น ๆ สำหรับเวอร์ชันก่อนหน้านี้
shosti

คุณต้องตั้งค่าพารามิเตอร์นี้ทุกครั้งที่รีสตาร์ทฐานข้อมูลหรือไม่? หรือหลังจากที่คุณทำครั้งเดียวคุณจะลืม? ขอบคุณ
fresko

5
SET SESSIONมีไว้สำหรับเซสชันปัจจุบันเท่านั้น (จะกลับไปเป็นค่าเริ่มต้นเมื่อคุณเปิดการเชื่อมต่อใหม่) คุณยังสามารถตั้งค่าพารามิเตอร์การกำหนดค่าในระดับฐานข้อมูลโดยใช้เช่นALTER DATABASE SET idle_in_transaction_session_timeout = '5min'หรือใช้ไฟล์คอนฟิกูเรชัน (ดูpostgresql.org/docs/current/static/config-setting.html )
shosti

22

ใน PostgreSQL 9.1 การเชื่อมต่อที่ไม่ได้ใช้งานกับแบบสอบถามต่อไปนี้ ช่วยให้ฉันสามารถปัดเป่าสถานการณ์ที่จำเป็นในการรีสตาร์ทฐานข้อมูล สิ่งนี้เกิดขึ้นโดยส่วนใหญ่เมื่อเปิดการเชื่อมต่อ JDBC และปิดไม่ถูกต้อง

SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';

1
pg_terminate_backend เข้าตั้งแต่ 8.4
Andrew Banks


0

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

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