2009-06-19 11 views
25

Python with psycopg2 kullanıyorum ve birkaç bin satır ekleyen günlük bir işlemden sonra tam bir VACUUM çalıştırmaya çalışıyorum.PostgreSQL - VACUUM'u işlem bloğu dışındaki koddan nasıl çalıştırılır?

psycopg2.InternalError: VACUUM cannot run inside a transaction block 

nasıl bir hareket kümesinin dışında koddan bu çalıştırırım: Sorun aşağıdaki hatayı alıyorum benim kodundaki VACUUM komutunu çalıştırmayı denediğinizde bu?

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

END TRANSAKSİYONU göndermeyi deneyin? – nosklo

+0

@nosklo, İyi öneri, ancak COMMIT ile aynı olan Postgres belgelerine göre. –

+0

SQLAlchemy'ı herhangi bir şansla kullanıyor musunuz? Benzer bir sorunla karşılaştım çünkü autocommit = true değerinde SqlAlchemy ayarı gerçekte * işlemleri kapatmaz. 'Set_isolation_level' kullanımı, psycopg2 bağlantısının dahili yöntemlerine erişen bir çalışmadır. –

cevap

49

Daha fazla arama yaptıktan sonra psycopg2 bağlantı nesnesinin isolation_level özelliğini keşfettim. Bu durumun 0 olarak değiştirilmesinin sizi bir işlem bloğundan çıkaracağı ortaya çıkıyor. Yukarıdaki sınıfın vakum yöntemini değiştirmek aşağıdakileri çözer. Ayrıca, yalıtım seviyesini daha önce olduğu gibi geri yüklediğimi de unutmayın (varsayılan olarak 1 gibi görünüyor).

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 (o sayfadaki sonuna yakın) bu bağlamda izolasyon seviyelerinin kısa bir açıklama sağlar.

+8

Veya: 'self.conn.set_isolation_level (psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)' –

1
: Bir fark yaparsa

, basit bir DB soyutlama sınıf var, bir alt kümesi (yapılmış çalıştırılabilir değil, istisna-kullanım ve ihmal Docstringler ve hat kapsayan ayarlamaları) bağlam için altında görüntülenir

Ben psycopg2 ve PostgreSQL bilmiyorum, ama sadece apsw ve SQLite, bu yüzden bir "psycopg2" yardım veremez düşünüyorum. Bir hareket kümesinin dışında

  • :

    Ama PostgreSQL SQLite yaptığı gibi benzer işe yarayabilecek de, bende yolunmuş, bu iki çalışma modu vardır Bu her SQL etrafında bir işlem bloğu olması anlama sahip olduğunu bir hareket kümesinin içinde operasyon

  • , yani "TRANSACTıON BEGIN" ile işaretlenmiş ve "END iŞLEM" Bu durumda

sonlandırılır, sorun erişim katmanı psycopg2 içinde olabilir. Normalde, bir taahhüt yapılıncaya kadar işlemlerin örtük bir şekilde yerleştirildiği bir şekilde çalıştığı zaman, bir vakum üretmenin "standart bir yolu" olmayacaktır. Tabii ki "psycopg2" nin özel "vakum" yöntemine veya örtülü işlemlerin başlatılmadığı özel bir çalışma moduna sahip olması mümkün olabilir.

Çoğu veritabanı veritabanına erişmek için bir kabuk programm vardır: böyle olasılıklar var olduğu zaman

, (erişim katmanı ;-) değiştirmeden) tek seçenek orada kalır. Program, bu kabuk programını bir boruyla (vakum-komutunu kabuğun içine girerek) çalıştırabilir, böylece vakum yapmak için kabuk programını kullanır. Vakum, bu şekilde yavaş bir işlem olduğundan, harici bir programın başlangıcı ihmal edilebilir olacaktır. Tabii ki, gerçek program daha önce hiç işlenmemiş işi yerine getirmeli, aksi takdirde ölü kilit durumu olabilir - vakum son işleminizin sonuna kadar beklemelidir.

+1

Detaylı cevabınız için teşekkürler. Çözümün "izolasyon seviyeleri" ile ilgili olduğu ortaya çıkıyor, cevabımı aşağıya bakın. Sihirli numaralar kaçınarak –

-3

Yapmayın - VAKUM FULL'e ihtiyacınız yok. Aslında Postgres'in yeni bir versiyonunu çalıştırırsanız (8,1 diyelim), normal VACUUM'u manuel olarak çalıştırmanız bile gerekmiyor.

+6

kullanım tarzınıza bağlı olarak, hala zamanlar vardır elle imho vakum mantıklı. – rfusca

+1

Artık var ama artık fazla değil. Ve kesinlikle VAKUM FULL olmamalıdır. –

+0

PostGres'e ve bazı büyük tablolara gidiyorum. Tüm kitaplar (8. * veya 9. * perspektifinden bahsederken), VACUUM ANALYZE'yi bir çok güncellemeden sonra veya otomatik olarak bir daemon ile manuel olarak çalıştırma hakkında konuşurlar. Onlar bittiğinde bu should kesinlikle VAKUMLU gibi, kamu hizmetleri – winwaed

3

Ayrıca, aynı zamanda Vakumlu tarafından verilen mesajlar almak veya kullanarak analiz edebilirsiniz:

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

bu komut baskısını bir liste gibi sorgu günlük mesajla Vakum ve Analiz:

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" 

Bu yararlı olabilir DBA ^^ tam vakum 'vakum analiz' ya da belli masif sonra 'reindex' zorlayarak, postgresql güncel sürümlerinde şüpheli iken

4

eylemler performansı artırabilir veya disk kullanımını temizleyebilir. Bu postgresql spesifik ve diğer veritabanları için doğru olanı yapmak için temizlenmelidir.

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) 

Maalesef, django tarafından sağlanan bağlantı proxy'si set_isolation_level'e erişim sağlamamaktadır. bir geçirme işlemi için Güney ile Django kullanıyorsanız

2

Not Bir VACUUM ANALYZE çalıştırmak için aşağıdaki kodu kullanabilirsiniz.

def forwards(self, orm): 

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

    #Optionally start another transaction to do some more work... 
    db.start_transaction()