इस लाभ की एक विशिष्ट लागत होती है: लेन-देन मोड चुपचाप उन सभी चीजों को तोड़ देता है जो एक अनुरोध से दूसरे अनुरोध तक स्थिर पोस्टग्रेज कनेक्शन मानता है। सत्र सेट, सुनें/सूचित करें, सलाहकार लॉक, कर्सर जो लेनदेन से बचे रहते हैं, तैयार विवरण नाम दिए गए हैं। यह आलेख तंत्र का विवरण देता है, इन सीमाओं को उनके सटीक लक्षणों के साथ सूचीबद्ध करता है, फिर दिखाता है कि उत्पादन में बैकएंड (हमारा, सीधे इसके भंडार में सत्यापित) इसे फंसने के बिना कैसे कॉन्फ़िगर करता है। यहां उद्धृत किसी भी प्रदर्शन आंकड़े के पीछे माप पद्धति के लिए, हमारी बेंचमार्क पद्धतिदेखें।
अनिवार्य है
- लेन-देन मोड: सर्वर कनेक्शन प्रत्येक लेन-देन के अंत में जारी किया जाता है, न कि तब जब क्लाइंट डिस्कनेक्ट हो जाता है। लघु REST API प्रकार के कनेक्शन साझा करने के लिए यह सबसे कुशल तरीका है।
- निर्माण द्वारा असंगत: सत्र सेट/रीसेट, सुनें/सूचित करें, सत्र सलाहकार लॉक, होल्ड कर्सर के साथ, एक अनुरोध से दूसरे अनुरोध में पुन: उपयोग की जाने वाली अस्थायी तालिकाएँ।
- व्यवहार में सबसे आम नुकसान: नामित तैयार कथन, जो कई ड्राइवर (sqlx, asyncpg, JDBC pgjdbc ड्राइवर) डिफ़ॉल्ट रूप से सक्रिय होते हैं, एक अलग सर्वर कनेक्शन पर दोबारा चलाए जा सकते हैं और लोड के तहत
prepared statement does not existजैसी त्रुटि को ट्रिगर कर सकते हैं। - संस्करण 1.21 के बाद से, PgBouncer लेनदेन मोड (सर्वर कनेक्शन के माध्यम से LRU कैश) में प्रोटोकॉल तैयार कथनों का पालन कर सकता है। यदि आपका एप्लिकेशन प्रत्येक अनुरोध पर
search_pathबदलता है तो यह क्लाइंट-साइड कैश को अक्षम करने से नहीं रोकता है। - ऑराबेस कोड में सत्यापित: किरायेदार पूल
statement_cache_capacity(0)और PgBouncer के साथpool_mode=transactionमें चलते हैं, जबकि PostgREST स्वेच्छा से LISTEN/NOTIFY के माध्यम से अपने स्कीमा पुनः लोड करने के लिए सीधे कनेक्शन में रहता है।
PgBouncer के 3 पूलिंग मोड
PgBouncer तीन मोड प्रदान करता है, जो केवल तभी भिन्न होता है जब पोस्टग्रेज सर्वर कनेक्शन सामान्य पूल में वापस आता है। आधिकारिक दस्तावेज़ में उनके नाम session, transaction और statement (pgbouncer.org/features.html, "पूलिंग मोड" अनुभाग, 24 अगस्त 2026 को एक्सेस किया गया) हैं।
| पहनावा | सर्वर कनेक्शन ढीला | सत्र अनुकूलता |
|---|---|---|
| सत्र (डिफ़ॉल्ट) | क्लाइंट डिस्कनेक्शन पर | कुल: सेट करें, सुनें, कर्सर, सब कुछ लाइव की तरह काम करता है |
| लेन-देन | प्रत्येक लेनदेन के अंत में (कमिट/रोलबैक) | आंशिक: केवल वही जो लेन-देन में स्थानीय रहता है |
| कथन | प्रत्येक व्यक्तिगत अनुरोध के बाद | न्यूनतम: स्पष्ट बहु-क्वेरी लेनदेन निषिद्ध है |
सत्र मोड सबसे अनुमेय है लेकिन स्केलेबिलिटी में सबसे कम प्रभावी है: एक पोस्टग्रेज कनेक्शन क्लाइंट के लिए तब तक आरक्षित रहता है जब तक वह जुड़ा रहता है, भले ही यह दो अनुरोधों के बीच कुछ भी नहीं करता है। स्टेटमेंट मोड बहुत विशिष्ट मामलों (केवल पढ़ने के लिए प्रॉक्सी, स्वास्थ्य-जाँच) के लिए आरक्षित है और यहां तक कि क्लासिक स्पष्ट लेनदेन को भी तोड़ देता है। लेन-देन मोड वह समझौता है जो REST API के लिए व्यवहार में हावी है: प्रत्येक HTTP अनुरोध आम तौर पर एक छोटे पोस्टग्रेज लेनदेन से मेल खाता है।
लेनदेन मोड कैसे काम करता है, कनेक्शन दर कनेक्शन
लेन-देन मोड में, PgBouncer केवल क्लाइंट के साथ एक सर्वर कनेक्शन जोड़ता है जब क्लाइंट लेन-देन खोलता है, और COMMIT या ROLLBACK पर इसे पूल में वापस कर देता है। दो लेन-देन के बीच, एक ही क्लाइंट खुद को पूरी तरह से अलग सर्वर कनेक्शन पर पुनः असाइन किया हुआ पा सकता है।
सीधे तौर पर, 20 के default_pool_size के साथ, PgBouncer एक साथ कई सौ ग्राहकों को अवशोषित कर सकता है, जिनके पास किसी भी समय, वास्तव में केवल कुछ ही लेनदेन प्रगति पर होते हैं। यह वह अनुपात है जो उच्च ट्रैफ़िक लेकिन छोटे लेनदेन वाले REST API के लिए लेनदेन मोड को उचित ठहराता है: दुर्लभ संसाधन (एक पोस्टग्रेज कनेक्शन, सर्वर साइड पर मेमोरी में महंगा) केवल उस समय के लिए कब्जा कर लिया जाता है जो कड़ाई से आवश्यक है।
यह अंतिम टिप्पणी सार प्रस्तुत करती है: लेनदेन मोड काम करता है क्योंकि यह जानबूझकर "मेरे एप्लिकेशन सत्र" और "मेरे पोस्टग्रेज कनेक्शन" के बीच के लिंक को तोड़ देता है। इस लिंक पर आधारित हर चीज़ टूट जाती है. अगला भाग सटीक रूप से क्या सूचीबद्ध करता है।
लेन-देन पूलिंग मोड में क्या टूटता है?
आधिकारिक PgBouncer दस्तावेज़ स्पष्ट रूप से PostgreSQL सुविधाओं को सूचीबद्ध करता है जो एक ही क्लाइंट से दो अनुरोधों के बीच सर्वर कनेक्शन को पुन: चक्रित करते ही अपना अर्थ खो देते हैं।
| प्रभावित कार्यक्षमता | ये क्यों टूटता है | विशिष्ट लक्षण |
|---|---|---|
| सेट / सेट सत्र | सेटिंग ऐसे कनेक्शन पर लागू होती है जिसे तुरंत बाद पुनर्चक्रित किया जा सकता है | ऐसा लगता है कि दो अनुरोधों के बीच एक पैरामीटर बेतरतीब ढंग से भूल गया है |
| सुनें/सूचित करें | सूचनाएं प्राप्त करने के लिए एक सतत कनेक्शन मानता है | ग्राहक को कभी भी सूचित नहीं किया जाता, या केवल रुक-रुक कर |
| सत्र सलाहकार ताले | लॉक सर्वर कनेक्शन द्वारा रखा जाता है, लॉजिकल क्लाइंट द्वारा नहीं | एक लॉक अपेक्षित पूर्णता से पहले रिलीज़ हो जाता है, या कभी रिलीज़ नहीं होता है |
| होल्ड स्लाइडर के साथ | इसे खोलने वाले लेन-देन से परे जीवित रहना चाहिए | अगले पुनरावृत्ति पर "कर्सर मौजूद नहीं है" त्रुटि |
| अस्थायी टेबल | पोस्टग्रेज़ सत्र से संबंधित, लेन-देन से नहीं | अगली क्वेरी पर तालिका "गायब" हो जाती है |
| नाम से तैयार बयान | एक विशिष्ट सर्वर कनेक्शन पर तैयार किया गया, दूसरे पर दोबारा चलाया गया | लोड के तहत "तैयार कथन ... मौजूद नहीं है"। |
इनमें से अधिकांश सीमाएँ स्थानीय विकास में प्रकट नहीं होती हैं, जहाँ एक ही कनेक्शन आम तौर पर सभी ट्रैफ़िक को पूरा करता है। वे वास्तविक लोड के तहत दिखाई देते हैं, जब कई क्लाइंट वास्तव में पूल साझा करते हैं और एक सर्वर कनेक्शन वास्तव में एक ही तार्किक क्लाइंट से दो अनुरोधों के बीच हाथ बदलता है। धूम्रपान परीक्षण लगभग कभी भी उन्हें प्रकट नहीं करता है।
तैयार किए गए कथन: सबसे गलत समझी जाने वाली सीमा
अधिकांश आधुनिक पोस्टग्रेज़ ड्राइवर, एप्लिकेशन कोड द्वारा स्पष्ट रूप से अनुरोध किए बिना, डिफ़ॉल्ट रूप से प्रोटोकॉल पक्ष पर नामित अनुरोध तैयार करते हैं। यही वह चीज़ है जिसके कारण इस जाल का अनुमान लगाना कठिन हो जाता है।
एक प्रोटोकॉल तैयार कथन को Parseके समय एक विशिष्ट सर्वर कनेक्शन पर नामित और कैश किया जाता है। लेन-देन मोड में, इस कनेक्शन को एक ही तार्किक क्लाइंट के दो अनुरोधों के बीच किसी अन्य क्लाइंट को पुन: असाइन किया जा सकता है। यदि ड्राइवर उसी स्टेटमेंट नाम को उस कनेक्शन पर दोबारा चलाता है जहां इसे कभी तैयार नहीं किया गया था, तो पोस्टग्रेज एक स्पष्ट त्रुटि के साथ प्रतिक्रिया करता है, आमतौर पर एक sqlx क्लाइंट के लिए prepared statement "sqlx_s_N" does not exist। व्यवहार रुक-रुक कर होता है: यह इस पर निर्भर करता है कि कनेक्शन लोड के तहत कैसा प्रदर्शन करता है, न कि प्रत्येक कॉल पर पुनरुत्पादित नियतात्मक बग पर।
भाषा की परवाह किए बिना क्लाइंट-साइड सुधार समान है: लेनदेन मोड में पूलर को पार करने वाले किसी भी पूल के लिए नामित तैयार कथनों के कैश को अक्षम करें, या अनाम प्रश्नों को बाध्य करें। रस्ट विद एसक्यूएलएक्स में, यह कनेक्शन विकल्पों पर statement_cache_capacity(0) से होकर गुजरता है।
संस्करण 1.21 के बाद से, PgBouncer सर्वर साइड पर कुछ हद तक समस्या को कम करता है: यह लेनदेन मोड में प्रोटोकॉल तैयार किए गए कथनों का पालन कर सकता है और उन्हें निर्दिष्ट कनेक्शन पर तुरंत तैयार कर सकता है, प्रति कनेक्शन LRU कैश के साथ जिसका आकार max_prepared_statementsके माध्यम से समायोजित किया जाता है। यह चूक की संख्या को कम करता है, लेकिन यह आपको मल्टी-टेनेंट पूल में क्लाइंट कैश को अक्षम करने से छूट नहीं देता है जहां search_path एक अनुरोध से दूसरे अनुरोध में बदलता है: एक कैश्ड प्लान Parseके समय हल की गई तालिका के आंतरिक पहचानकर्ता (ओआईडी) को फ्रीज कर देता है, और इसे किसी अन्य स्कीमा के तहत दोबारा चलाने से एक साधारण त्रुटि के बजाय गलत किरायेदार से डेटा वापस आ सकता है।
ऑराबेस लेनदेन मोड में PgBouncer को कैसे कॉन्फ़िगर करता है
ऑराबेस रिपॉजिटरी साझा डेटा प्लेन (deploy/helm/aurabase/templates/infra/pgbouncer.yaml) के सामने PgBouncer को pool_mode=transaction के रूप में तैनात करता है, और एक किरायेदार (deploy/cnpg/tenant-pooler.yaml) के प्रत्येक समर्पित पोस्टग्रेज इंस्टेंस के सामने एक समान रूप से कॉन्फ़िगर किया गया Pooler CNPG तैनात करता है। दोनों रास्ते ऊपर वर्णित समान अनुशासन लागू करते हैं।
स्रोत कोड इस विकल्प के लिए एक विशिष्ट सुरक्षा कारण का दस्तावेजीकरण करता है, न कि केवल स्थिरता का कारण। किरायेदारों के बीच साझा किए गए पोस्टग्रेज़ पूल पुन: उपयोग किए गए कनेक्शन पर प्रति प्रोजेक्ट एक अलग search_path स्थिति देते हैं। एक कैश्ड तैयार कथन Parseके समय हल की गई तालिका के OID को फ्रीज कर देता है; उसी कनेक्शन पर किसी अन्य किरायेदार के लिए इसे दोबारा चलाने से पहले किरायेदार की स्कीमा, एक अलगाव बाईपास के खिलाफ क्वेरी चलेगी, न कि केवल एक एप्लिकेशन त्रुटि। इसलिए statement_cache_capacity(0) को बिना किसी अपवाद के लागू किया जाता है, जिसमें समर्पित उदाहरण भी शामिल हैं जो लेनदेन मोड में सीएनपीजी पूलर से गुजरते हैं।
दूसरा सत्र स्वच्छता उपाय: जब प्रत्येक कनेक्शन पूल में लौटता है, तो एक हुक DISCARD ALL निष्पादित करता है (सेटिंग्स को रीसेट करना, सर्वर साइड पर तैयार कथनों को हटाना, सलाहकार लॉक जारी करना, कर्सर और अस्थायी तालिकाओं को शुद्ध करना)। इस हुक के बिना, पिछले अनुरोध द्वारा उत्पन्न सत्र अवशेष उसी पुनर्नवीनीकरण कनेक्शन का पुन: उपयोग करने वाले एक अलग किरायेदार से अगले अनुरोध पर लीक हो सकता है।
अपवाद स्वीकृत: समर्पित PostgREST इंस्टेंसेस पूलर से गुजरे बिना, प्राथमिक से सीधे संबंध में रहते हैं। PostgREST स्कीमा रीलोडिंग LISTEN/NOTIFYपर निर्भर करती है, जो एक सतत कनेक्शन मानता है, बिल्कुल वही कार्यक्षमता जो लेनदेन मोड को तोड़ देती है (हमारे लेख में PostgREST संगतता Aurabaseपर विवरण पहले से ही प्रलेखित है)। प्रति अनुरोध आरएलएस सेटिंग्स एक स्पष्ट लेनदेन के भीतर SET LOCAL को भेज दी जाती हैं, जो पूल के साथ संगत रहने का एकमात्र तरीका है जो किसी भी COMMIT पर सर्वर कनेक्शन बदल सकता है (बहु-किरायेदार आरएलएस अलगावपर हमारा लेख देखें)।
अपने एप्लिकेशन को तोड़े बिना लेनदेन मोड सक्षम करें
एक छोटी चेकलिस्ट, लेनदेन मोड में सीधे पोस्टग्रेज कनेक्शन से पीजीबाउंसर तक जाने वाले किसी भी बैकएंड पर लागू होती है।
- एप्लिकेशन कोड का ऑडिट करें। गैर-लेनदेन
SET,LISTEN/NOTIFY, सत्र सलाहकार लॉक,WITH HOLDकर्सर और प्रश्नों के बीच पुन: उपयोग की जाने वाली अस्थायी तालिकाओं को देखें। - एक स्पष्ट लेनदेन के भीतर सत्र सेट को स्थानीय सेट से बदलें। यह एकमात्र सेटिंग है जो कनेक्शन रीसाइक्लिंग से ठीक से बच जाती है, क्योंकि इसे अगले कनेक्शन पर लीक होने के बजाय COMMIT/रोलबैक पर साफ किया जाता है।
- यदि आपका पूल पूलर को पार करता है और स्कीमा या भूमिका एक अनुरोध से दूसरे अनुरोध में बदल जाती है, तो ड्राइवर-साइड तैयार स्टेटमेंट कैश को अक्षम करें। प्रदर्शन में लागत वास्तविक है लेकिन मापने योग्य है, और किरायेदारों के बीच रिसाव के जोखिम से बहुत कम है।
- उन कनेक्शनों को अलग करें जिनके लिए वास्तव में सत्र मोड (माइग्रेशन, एडमिन स्क्रिप्ट, कुछ भी जो LISTEN/NOTIFY पर निर्भर करता है) को अन्य सभी ट्रैफ़िक के लिए लेनदेन मोड को छोड़ने के बजाय सीधे गैर-पूलर कनेक्शन में अलग करें।
- आकार
default_pool_sizeऔरmax_client_connपोस्टग्रेज के वास्तविकmax_connectionsके सापेक्ष, किसी अन्य प्रोजेक्ट से कॉपी किए गए मनमाने आंकड़े से नहीं। - वास्तविक भार के तहत परीक्षण करें, न कि केवल धूम्रपान परीक्षण। तैयार कथन त्रुटियां और सत्र सेटिंग्स लीक लगभग कभी भी एक स्थानीय कनेक्शन पर दिखाई नहीं देते हैं।
- उत्पादन में एक बार PgBouncer प्रशासन कंसोल से
SHOW POOLSऔरSHOW STATSकी निगरानी करें, ताकि क्लाइंट साइड पर दिखाई देने से पहले पूल संतृप्ति का पता लगाया जा सके।
क्या आपको हमेशा सत्र के बजाय लेनदेन मोड चुनना चाहिए?
नहीं, लेकिन अधिकांश REST API के लिए यह सही डिफ़ॉल्ट विकल्प है। सत्र मोड एक विरासत एप्लिकेशन के लिए बेहतर रहता है जो सत्र कार्यात्मकताओं पर अत्यधिक निर्भर होता है जिसे आप जल्दी से रिफैक्टर नहीं कर सकते हैं, या कम ट्रैफ़िक के लिए जहां पूलिंग लाभ माइग्रेशन प्रयास की भरपाई नहीं करता है।
पीजीबाउंसर इस पूलिंग मॉडल का एकमात्र कार्यान्वयन नहीं है: सुपरवाइजर (सुपाबेस) और पीजीकैट दो हालिया विकल्प हैं, जिनमें लोड वितरण और क्लस्टरिंग पर अलग-अलग ट्रेड-ऑफ हैं। अपनी टोपोलॉजी के आधार पर तीनों के बीच चयन करने के लिए हमारी विस्तृत तुलना, PgBouncer बनाम Supavisor बनाम PgCatदेखें।
पूछे जाने वाले प्रश्न
उत्पादन में लेन-देन मोड सक्रिय होने के बाद अक्सर जो प्रश्न सामने आते हैं।