PostgreSQL पर आक्रामक ऑटोवैक्यूम


42

मैं अपने डेटाबेस को आक्रामक रूप से ऑटो वैक्यूम करने के लिए PostgreSQL प्राप्त करने की कोशिश कर रहा हूं। मैंने वर्तमान में ऑटो वैक्यूम को निम्न प्रकार से कॉन्फ़िगर किया है:

  • autovacuum_vacuum_cost_delay = 0 # लागत आधारित वैक्यूम बंद करें
  • autovacuum_vacuum_cost_limit = 10000 # मान
  • autovacuum_vacuum_threshold = 50 # मूल्य मान
  • autovacuum_vacuum_scale_factor = 0.2 # मूल्य मान

मैं ध्यान देता हूं कि जब डेटाबेस लोड के अधीन नहीं होता है, तो ऑटो वैक्यूम केवल किक करता है, इसलिए मैं उन स्थितियों में पहुंच जाता हूं जहां जीवित ट्यूपल्स की तुलना में कहीं अधिक मृत ट्यूपल हैं। उदाहरण के लिए संलग्न स्क्रीनशॉट देखें। तालिकाओं में से एक में 23 जीवित टुपल्स हैं लेकिन वैक्यूम के इंतजार में 16845 मृत टुपल्स हैं। यह पागलपन है!

बहुत सारे डेड ट्यूपल्स

जब टेस्ट रन समाप्त हो जाता है और डेटाबेस सर्वर निष्क्रिय हो जाता है, तो ऑटो वैक्यूम किक करता है, जो कि मैं वैसा नहीं चाहता, जैसा कि मैं चाहता हूं कि जब भी मृत टुपल्स की संख्या 20% से अधिक हो जाए, तो डेटाबेस को किक के रूप में ऑटो वैक्यूम को किक करना होगा। कॉन्फ़िगर किया गया। सर्वर के बेकार होने पर ऑटो वैक्यूम मेरे लिए बेकार है, क्योंकि प्रोडक्शन सर्वर को निरंतर अवधि के लिए अपडेट / सेकेंड के हिट होने की उम्मीद है, यही वजह है कि सर्वर के लोड होने पर भी मुझे ऑटो वैक्यूम चलाने की आवश्यकता होती है।

क्या ऐसा कुछ है जो मुझे याद आ रहा है? मैं ऑटो वैक्यूम को चलाने के लिए कैसे मजबूर करूं, जबकि सर्वर भारी लोड के तहत है?

अपडेट करें

क्या यह लॉकिंग मुद्दा हो सकता है? विचाराधीन तालिकाएं सारांश तालिकाएं हैं जो एक सम्मिलित आवेषण ट्रिगर के माध्यम से पॉपुलेटेड हैं। समान तालिकाओं को एक ही पंक्ति में रोकने के लिए इन तालिकाओं को SHAR ROW EXCLUSIVE मोड में बंद किया जाता है।

जवाबों:


40

Eelke लगभग निश्चित रूप से सही है कि आपका लॉकिंग ऑटोवैक्म को रोक रहा है। ऑटोवैक्यूम को जानबूझकर, उपयोगकर्ता गतिविधि के लिए रास्ता देने के लिए डिज़ाइन किया गया है। यदि उन तालिकाओं को बंद कर दिया जाता है, तो ऑटोवैक्यूम उन्हें वैक्यूम नहीं कर सकता है।

पोस्टपेरिटी के लिए, हालाँकि, मैं हाइपर-आक्रामक ऑटोवैक्यूम के लिए सेटिंग्स का एक उदाहरण सेट देना चाहता था, क्योंकि आपके द्वारा दी गई सेटिंग्स ऐसा नहीं करती हैं। ध्यान दें कि ऑटोवैक्यूम को अधिक आक्रामक बनाना आपकी समस्या को हल करने की संभावना नहीं है, हालांकि। यह भी ध्यान दें कि डिफ़ॉल्ट ऑटोवैक्यूम सेटिंग्स 200 से अधिक टेस्ट रन पर आधारित होती हैं, जो डीबीटी 2 का उपयोग करके सेटिंग्स का एक इष्टतम संयोजन की मांग करते हैं, इसलिए चूक को तब तक अच्छा माना जाना चाहिए जब तक कि आपके पास अन्यथा सोचने का ठोस कारण न हो, या जब तक कि आपका डेटाबेस काफी बाहर न हो। OLTP डेटाबेस के लिए मुख्य धारा (जैसे एक छोटा डेटाबेस जो प्रति सेकंड 10K अपडेट या 3TB डेटा वेयरहाउस मिलता है)।

सबसे पहले, लॉगिंग चालू करें ताकि आप इस बात की जांच कर सकें कि क्या ऑटोवैक्यूम वह कर रहा है जो आपको लगता है कि यह है:

log_autovacuum_min_duration = 0

तो चलिए अधिक ऑटोवैक श्रमिकों को बनाते हैं और उन्हें अधिक बार तालिकाओं की जांच करते हैं:

autovacuum_max_workers = 6
autovacuum_naptime = 15s

चलो ऑटो-वैक्यूम के लिए थ्रेसहोल्ड को कम करते हैं और जल्द ही ट्रिगर करने के लिए ऑटो-विश्लेषण करते हैं:

autovacuum_vacuum_threshold = 25
autovacuum_vacuum_scale_factor = 0.1

autovacuum_analyze_threshold = 10
autovacuum_analyze_scale_factor = 0.05 

तो चलिए ऑटोकैसम को कम बाधित करते हैं, इसलिए यह तेजी से पूरा होता है, लेकिन समवर्ती उपयोगकर्ता गतिविधि पर अधिक प्रभाव पड़ने की कीमत पर:

autovacuum_vacuum_cost_delay = 10ms
autovacuum_vacuum_cost_limit = 1000

सामान्य रूप से आक्रामक ऑटोवैक्यूम के लिए आपका पूरा कार्यक्रम है, जो एक छोटे डेटाबेस के लिए अद्यतनों की उच्च दर प्राप्त करने के लिए उचित हो सकता है, लेकिन समवर्ती उपयोगकर्ता गतिविधि पर बहुत अधिक प्रभाव पड़ सकता है।

इसके अलावा, ध्यान दें कि ऑटोवैकोम पैरामीटर को प्रति तालिका समायोजित किया जा सकता है , जो ऑटोवेक्यूम के व्यवहार को समायोजित करने की आवश्यकता के लिए लगभग हमेशा एक बेहतर उत्तर है।

फिर, हालांकि, यह आपकी वास्तविक समस्या का समाधान करने की संभावना नहीं है।


36

बस यह देखने के लिए कि कौन-सी तालिकाएँ ऑटोवैकोम के लिए योग्य हैं, निम्नलिखित क्वेरी का उपयोग किया जा सकता है ( http://www.postgresql.org/docs/current/static/routine-vacuuming.html पर आधारित )। हालाँकि, ध्यान दें कि क्वेरी तालिका विशिष्ट सेटिंग्स की तलाश में नहीं है:

 SELECT psut.relname,
     to_char(psut.last_vacuum, 'YYYY-MM-DD HH24:MI') as last_vacuum,
     to_char(psut.last_autovacuum, 'YYYY-MM-DD HH24:MI') as last_autovacuum,
     to_char(pg_class.reltuples, '9G999G999G999') AS n_tup,
     to_char(psut.n_dead_tup, '9G999G999G999') AS dead_tup,
     to_char(CAST(current_setting('autovacuum_vacuum_threshold') AS bigint)
         + (CAST(current_setting('autovacuum_vacuum_scale_factor') AS numeric)
            * pg_class.reltuples), '9G999G999G999') AS av_threshold,
     CASE
         WHEN CAST(current_setting('autovacuum_vacuum_threshold') AS bigint)
             + (CAST(current_setting('autovacuum_vacuum_scale_factor') AS numeric)
                * pg_class.reltuples) < psut.n_dead_tup
         THEN '*'
         ELSE ''
     END AS expect_av
 FROM pg_stat_user_tables psut
     JOIN pg_class on psut.relid = pg_class.oid
 ORDER BY 1;

11

हाँ यह एक लॉकिंग मुद्दा है। इस पृष्ठ के अनुसार (गैर-पूर्ण) VACUUM को SHARE UPDATE EXCLUSIVE पहुंच की आवश्यकता होती है, जो आपके द्वारा उपयोग किए जा रहे लॉक स्तर से अवरुद्ध होता है।

क्या आप निश्चित हैं कि आपको इस लॉक की आवश्यकता है? PostgreSQL ACID के अनुरूप है, इसलिए समवर्ती लेखन ज्यादातर मामलों में एक समस्या है क्योंकि PostgreSQL लेनदेन में से एक को रद्द कर देगा यदि धारावाहिकीकरण उल्लंघन होगा।

इसके अलावा आप पूरे तालिका के बजाय पंक्तियों को लॉक करने के लिए SELECT FOR UPDATE का उपयोग करके पंक्तियों को लॉक कर सकते हैं ।

लॉकिंग के बिना एक अन्य विकल्प लेन-देन के अलगाव स्तर का उपयोग करना होगा । हालांकि यह अन्य लेनदेन के प्रदर्शन को प्रभावित कर सकता है और आपको अधिक क्रमिक विफलताओं के लिए तैयार रहना चाहिए।


यह सारांश तालिकाओं को लॉक करने के कारण है, क्योंकि ये SHARE ROW EXCLUSIVE MODE का उपयोग करके लॉक किए गए हैं। समवर्ती लेखन ताला के बिना सफल हो सकता है, लेकिन वे निश्चित रूप से गलत मूल्यों के साथ समाप्त होने जा रहे हैं। कल्पना कीजिए कि मैं टाइप X की पंक्तियों की एक गिनती N बना रहा हूं। अगर मैं समवर्ती प्रकार की 2 पंक्तियाँ सम्मिलित करता हूं, तो बिना लॉक किए मैं N + 2 के बजाय अपनी सारांश तालिका में N + 1 के साथ समाप्त हो जाऊंगा। मैंने जो समाधान अपनाया है। एक क्रोन नौकरी है जो मैन्युअल रूप से मेरे डेटाबेस में सारांश तालिकाओं को खाली करती है। यह अच्छी तरह से काम करता है और अनुशंसित दृष्टिकोण प्रतीत होता है, लेकिन यह मेरे लिए एक हैक की तरह बहुत अधिक लगता है।
CadentOrange

6

ऑटोवैकोम प्रक्रियाओं की संख्या में वृद्धि और नैप्टाइम को कम करने से संभवतः मदद मिलेगी। यहाँ PostgreSQL 9.1 के लिए कॉन्फ़िगरेशन है जो मैं बैकअप जानकारी संग्रहीत करने वाले सर्वर पर उपयोग करता हूं और परिणामस्वरूप बहुत सी सम्मिलित गतिविधि मिलती है।

http://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html

autovacuum_max_workers = 6              # max number of autovacuum subprocesses
autovacuum_naptime = 10         # time between autovacuum runs
autovacuum_vacuum_cost_delay = 20ms     # default vacuum cost delay for

cost_delayवैक्यूमिंग को और अधिक आक्रामक बनाने के लिए मैं इसे कम करने की कोशिश करूंगा ।

मैं भी pgbench का उपयोग करके ऑटोवैक्युमिंग का परीक्षण कर सकता हूं।

http://wiki.postgresql.org/wiki/Pgbenchtesting

उच्च विवाद उदाहरण:

मानक बनाने के लिए bench_replication डेटाबेस

pgbench -i -p 5433 bench_replication

Pgbench चलाएं

pgbench -U postgres -p 5432 -c 64 -j 4 -T 600 bench_replication

ऑटोकैसमिंग स्थिति की जाँच करें

psql
>\connect bench_replicaiton
bench_replication=# select schemaname, relname, last_autovacuum from pg_stat_user_tables;
 schemaname |     relname      |        last_autovacuum        
------------+------------------+-------------------------------
 public     | pgbench_branches | 2012-07-18 18:15:34.494932+02
 public     | pgbench_history  | 
 public     | pgbench_tellers  | 2012-07-18 18:14:06.526437+02
 public     | pgbench_accounts | 

6

मौजूदा "ऑटोवैक्यूम के लिए अर्हता प्राप्त" स्क्रिप्ट बहुत उपयोगी है, लेकिन (जैसा कि सही ढंग से कहा गया है) तालिका के विशिष्ट विकल्प गायब थे। यहां इसका संशोधित संस्करण है जो उन विकल्पों को ध्यान में रखता है:

WITH rel_set AS
(
    SELECT
        oid,
        CASE split_part(split_part(array_to_string(reloptions, ','), 'autovacuum_vacuum_threshold=', 2), ',', 1)
            WHEN '' THEN NULL
        ELSE split_part(split_part(array_to_string(reloptions, ','), 'autovacuum_vacuum_threshold=', 2), ',', 1)::BIGINT
        END AS rel_av_vac_threshold,
        CASE split_part(split_part(array_to_string(reloptions, ','), 'autovacuum_vacuum_scale_factor=', 2), ',', 1)
            WHEN '' THEN NULL
        ELSE split_part(split_part(array_to_string(reloptions, ','), 'autovacuum_vacuum_scale_factor=', 2), ',', 1)::NUMERIC
        END AS rel_av_vac_scale_factor
    FROM pg_class
) 
SELECT
    PSUT.relname,
    to_char(PSUT.last_vacuum, 'YYYY-MM-DD HH24:MI')     AS last_vacuum,
    to_char(PSUT.last_autovacuum, 'YYYY-MM-DD HH24:MI') AS last_autovacuum,
    to_char(C.reltuples, '9G999G999G999')               AS n_tup,
    to_char(PSUT.n_dead_tup, '9G999G999G999')           AS dead_tup,
    to_char(coalesce(RS.rel_av_vac_threshold, current_setting('autovacuum_vacuum_threshold')::BIGINT) + coalesce(RS.rel_av_vac_scale_factor, current_setting('autovacuum_vacuum_scale_factor')::NUMERIC) * C.reltuples, '9G999G999G999') AS av_threshold,
    CASE
        WHEN (coalesce(RS.rel_av_vac_threshold, current_setting('autovacuum_vacuum_threshold')::BIGINT) + coalesce(RS.rel_av_vac_scale_factor, current_setting('autovacuum_vacuum_scale_factor')::NUMERIC) * C.reltuples) < PSUT.n_dead_tup
        THEN '*'
    ELSE ''
    END AS expect_av
FROM
    pg_stat_user_tables PSUT
    JOIN pg_class C
        ON PSUT.relid = C.oid
    JOIN rel_set RS
        ON PSUT.relid = RS.oid
ORDER BY C.reltuples DESC;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.