2009-06-19 7 views
25

मैं psycopg2 के साथ पायथन का उपयोग कर रहा हूं और मैं एक दैनिक ऑपरेशन के बाद एक पूर्ण VACUUM चलाने की कोशिश कर रहा हूं जो कई हजार पंक्तियों को सम्मिलित करता है।PostgreSQL - लेनदेन ब्लॉक के बाहर कोड से VACUUM कैसे चलाएं?

psycopg2.InternalError: VACUUM cannot run inside a transaction block 

मैं इस कोड से कोई लेन-देन ब्लॉक के बाहर चला सकता हूँ: समस्या जब मैं अपने कोड मैं निम्नलिखित त्रुटि मिलती भीतर VACUUM आदेश चलाने का प्रयास है?

class db(object): 
    def __init__(dbname, host, port, user, password): 
     self.conn = psycopg2.connect("dbname=%s host=%s port=%s \ 
             user=%s password=%s" \ 
             % (dbname, host, port, user, password)) 

     self.cursor = self.conn.cursor() 

    def _doQuery(self, query): 
     self.cursor.execute(query) 
     self.conn.commit() 

    def vacuum(self): 
     query = "VACUUM FULL" 
     self._doQuery(query) 
+1

अंत ट्रांज़ेक्शन भेजने का प्रयास करें? – nosklo

+0

@ नोस्क्लो, अच्छा सुझाव, लेकिन पोस्टग्रेज़ दस्तावेज़ों के अनुसार जो COMMIT के समान है। –

+0

क्या आप किसी भी मौके से SQLAlchemy का उपयोग कर रहे हैं? मैंने एक समान समस्या का अनुभव किया क्योंकि autocommit = SqlAlchemy में True को वास्तव में * लेनदेन बंद नहीं करता है। 'Set_isolation_level' का उपयोग करना एक ऐसा काम है जो psycopg2 कनेक्शन के आंतरिक तरीकों तक पहुंचता है। –

उत्तर

49

अधिक खोज के बाद मैंने psycopg2 कनेक्शन ऑब्जेक्ट की अलगाव_लेवल संपत्ति की खोज की है। यह पता चला है कि इसे 0 में बदलकर आपको लेनदेन ब्लॉक से बाहर ले जाया जाएगा। उपर्युक्त वर्ग की वैक्यूम विधि को निम्नलिखित में बदलना इसे हल करता है। ध्यान दें कि मैंने अलग-अलग स्तर को अलगाव स्तर पर भी सेट किया है जो पहले था (डिफ़ॉल्ट रूप से 1 होने पर)।

def vacuum(self): 
    old_isolation_level = self.conn.isolation_level 
    self.conn.set_isolation_level(0) 
    query = "VACUUM FULL" 
    self._doQuery(query) 
    self.conn.set_isolation_level(old_isolation_level) 

This article (उस पृष्ठ पर अंत के पास) इस संदर्भ में अलगाव के स्तर की एक संक्षिप्त व्याख्या प्रदान करता है।

+8

या, जादू संख्याओं से परहेज करें: 'self.conn.set_isolation_level (psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) ' –

1
:

यदि यह एक फर्क नहीं पड़ता, मैं एक साधारण डीबी अमूर्त वर्ग है, जिनमें से एक सबसेट संदर्भ (runnable नहीं, अपवाद-हैंडलिंग और छोड़े गए docstrings और लाइन में फैले समायोजन किया) के लिए नीचे प्रदर्शित होता है

मुझे psycopg2 और PostgreSQL नहीं पता, लेकिन केवल एपीएसडब्ल्यू और एसक्यूएलएट, इसलिए मुझे लगता है कि मैं "psycopg2" मदद नहीं दे सकता।

  • एक सौदे ब्लॉक के बाहर::

    लेकिन यह मेरे लिए तेजी, कि PostgreSQL समान SQLite करता है के रूप में काम कर सकते हैं, यह आपरेशन के दो स्वरूप हैं यह हर एक एसक्यूएल के चारों ओर एक लेन-देन ब्लॉक के लिए अर्थ की दृष्टि से बराबर है आपरेशन

  • एक सौदे ब्लॉक के अंदर, कि "लेन-देन शुरू" द्वारा चिह्नित और "अंत लेन-देन"

जब यह मामला है के द्वारा समाप्त हो गया है, समस्या का उपयोग परत psycopg2 अंदर हो सकता है। जब यह सामान्य रूप से इस तरह से संचालित होता है कि प्रतिबद्धता पूरी तरह से तब तक डाली जाती है जब तक प्रतिबद्धता नहीं की जाती है, तो वैक्यूम बनाने के लिए कोई "मानक तरीका" नहीं हो सकता है।

बेशक यह संभव हो सकता है कि "psycopg2" में इसकी विशेष "वैक्यूम" विधि है, या एक विशेष ऑपरेशन मोड है, जहां कोई अंतर्निहित लेनदेन शुरू नहीं हुआ है।

अधिकांश डेटाबेस डेटाबेस तक पहुँचने का एक खोल programm है:

जब ऐसी कोई संभावनाएं मौजूद है, वहाँ एक ही विकल्प (पहुँच परत ;-) बदले बिना) रहता है। कार्यक्रम इस खोल कार्यक्रम को एक पाइप (वैक्यूम-कमांड को खोल में प्रवेश कर) के साथ चला सकता है, इस प्रकार वैक्यूम बनाने के लिए शैल प्रोग्राम का उपयोग कर सकता है। चूंकि वैक्यूम धीमा ऑपरेशन है, इसलिए बाहरी प्रोग्राम की शुरुआत उपेक्षित होगी। बेशक, वास्तविक कार्यक्रम को पहले सभी असामान्य काम करना चाहिए, अन्यथा मृत-लॉक स्थिति हो सकती है - वैक्यूम को आपके पिछले लेनदेन के अंत तक इंतजार करना चाहिए।

+1

आपके विस्तृत उत्तर के लिए धन्यवाद। यह पता चला है कि समाधान "अलगाव स्तर" के साथ करना था, नीचे मेरा जवाब देखें। –

-3

ऐसा न करें - आपको वैक्यूम पूर्ण की आवश्यकता नहीं है। दरअसल यदि आप पोस्टग्रेज़ के कुछ हालिया संस्करण चलाते हैं (मान लें> 8.1) आपको मैन्युअल रूप से सादे VACUUM चलाने की भी आवश्यकता नहीं है।

+6

आपके उपयोग पैटर्न के आधार पर, अभी भी वैक्यूम मैन्युअल रूप से वैक्यूम को समझ में आता है। – rfusca

+1

वहाँ हैं, लेकिन अब और भी नहीं हैं। और यह निश्चित रूप से वैक्यूम पूर्ण नहीं होना चाहिए। –

+0

मैं पोस्टग्रेस में और कुछ बड़ी टेबलों में जा रहा हूं। सभी किताबें (8. * या 9 * परिप्रेक्ष्य से बात कर रहे हैं) कई अद्यतनों के बाद मैन्युअल रूप से वाक्यूम विश्लेषण चलाने के बारे में बात करते हैं, या स्वचालित रूप से एक डिमन के साथ। – winwaed

3

साथ ही, आपको भी वैक्यूम द्वारा दिए गए संदेश प्राप्त या का उपयोग करते हुए विश्लेषण कर सकते हैं:

>> print conn.notices #conn is the connection object 

इस आदेश प्रिंट की तरह प्रश्नों की लॉग संदेश के साथ एक सूची वैक्यूम और विश्लेषण करें:

INFO: "usuario": processados 1 de 1 páginas, contendo 7 registros vigentes e 0 registros não vigentes; 7 registros amostrados, 7 registros totais estimados 
INFO: analisando "public.usuario" 

यह डीबीए के लिए उपयोगी हो सकता है ^^

4

जबकि वैक्यूम पूर्ण पोस्टग्रेस्क्ल के मौजूदा संस्करणों में संदिग्ध है, कुछ बड़े पैमाने पर 'वैक्यूम विश्लेषण' या 'रेइन्डेक्स' को मजबूर करना कार्य प्रदर्शन में सुधार कर सकते हैं, या डिस्क उपयोग को साफ कर सकते हैं। यह postgresql विशिष्ट है, और अन्य डेटाबेस के लिए सही काम करने के लिए साफ करने की जरूरत है।

from django.db import connection 
# Much of the proxy is not defined until this is done 
force_proxy = connection.cursor() 
realconn=connection.connection 
old_isolation_level = realconn.isolation_level 
realconn.set_isolation_level(0) 
cursor = realconn.cursor() 
cursor.execute('VACUUM ANALYZE') 
realconn.set_isolation_level(old_isolation_level) 

दुर्भाग्य से django द्वारा प्रदान की गई कनेक्शन प्रॉक्सी set_isolation_level तक पहुंच प्रदान नहीं करती है।

2

नोट करें कि यदि आप माइग्रेशन करने के लिए दक्षिण के साथ Django का उपयोग कर रहे हैं तो आप VACUUM ANALYZE निष्पादित करने के लिए निम्न कोड का उपयोग कर सकते हैं।

def forwards(self, orm): 

    db.commit_transaction() 
    db.execute("VACUUM ANALYZE <table>") 

    #Optionally start another transaction to do some more work... 
    db.start_transaction() 
संबंधित मुद्दे