2010-11-17 12 views
273

SQLAlchemy में flush() और commit() के बीच क्या अंतर है?SQLAlchemy: फ्लश() और प्रतिबद्ध() के बीच क्या अंतर है?

मैंने दस्तावेज़ पढ़ लिए हैं, लेकिन कोई भी बुद्धिमान नहीं है - ऐसा लगता है कि मेरे पास कोई पूर्व-समझ नहीं है जो मेरे पास नहीं है।

मुझे विशेष रूप से स्मृति उपयोग पर उनके प्रभाव में रूचि है। मैं फाइलों की एक श्रृंखला (कुल में लगभग 5 मिलियन पंक्तियों) से डेटाबेस में कुछ डेटा लोड कर रहा हूं और मेरा सत्र कभी-कभी गिर रहा है - यह एक बड़ा डेटाबेस है और मशीन बहुत अधिक स्मृति नहीं है।

मुझे आश्चर्य है कि क्या मैं commit() का उपयोग कर रहा हूं और पर्याप्त flush() कॉल नहीं कर रहा हूं - लेकिन वास्तव में यह समझने के बिना कि अंतर क्या है, यह कहना मुश्किल है!

उत्तर

334

एक सत्र वस्तु मूल रूप से डेटाबेस (अद्यतन, सम्मिलित, हटाएं) में परिवर्तनों का एक सतत लेनदेन है। ये ऑपरेशन तब तक डेटाबेस तक नहीं बने रहते जब तक कि वे प्रतिबद्ध नहीं होते हैं (यदि आपका प्रोग्राम मिड-सत्र लेनदेन में किसी कारण से बंद हो जाता है, तो कोई भी असामान्य परिवर्तन खो जाता है)।

सत्र ऑब्जेक्ट session.add() के साथ लेनदेन संचालन पंजीकृत करता है, लेकिन session.flush() को तब तक डेटाबेस में संवाद नहीं करता है।

session.flush() डेटाबेस (सम्मिलित, अद्यतन, हटाएं) में संचालन की एक श्रृंखला को संचारित करता है। डेटाबेस उन्हें लेनदेन में लंबित संचालन के रूप में रखता है। परिवर्तन डिस्क पर स्थायी रूप से जारी नहीं होते हैं, या अन्य लेन-देन के लिए दृश्यमान नहीं होते हैं जब तक कि डेटाबेस वर्तमान लेनदेन के लिए COMMIT प्राप्त नहीं करता है (जो session.commit() करता है)।

session.commit() डेटाबेस में उन परिवर्तनों को जारी रखता है (बनी रहती है)।

flush()हमेशाcommit() (1) के लिए एक कॉल के हिस्से के रूप में कहा जाता है।

जब आप डेटाबेस क्वेरी करने के लिए सत्र ऑब्जेक्ट का उपयोग करते हैं, तो क्वेरी डेटाबेस से और असामान्य लेनदेन के फ़्लश किए गए हिस्सों से परिणाम लौटाएगी। डिफ़ॉल्ट रूप से, सत्र ऑब्जेक्ट autoflush उनके संचालन करता है, लेकिन इसे अक्षम किया जा सकता है।

उम्मीद है कि इस उदाहरण यह स्पष्ट कर देगा:

#--- 
s = Session() 

s.add(Foo('A')) # The Foo('A') object has been added to the session. 
       # It has not been committed to the database yet, 
       # but is returned as part of a query. 
print 1, s.query(Foo).all() 
s.commit() 

#--- 
s2 = Session() 
s2.autoflush = False 

s2.add(Foo('B')) 
print 2, s2.query(Foo).all() # The Foo('B') object is *not* returned 
          # as part of this query because it hasn't 
          # been flushed yet. 
s2.flush()     # Now, Foo('B') is in the same state as 
          # Foo('A') was above. 
print 3, s2.query(Foo).all() 
s2.rollback()    # Foo('B') has not been committed, and rolling 
          # back the session's transaction removes it 
          # from the session. 
print 4, s2.query(Foo).all() 

#--- 
Output: 
1 [<Foo('A')>] 
2 [<Foo('A')>] 
3 [<Foo('A')>, <Foo('B')>] 
4 [<Foo('A')>] 
+0

बस एक और बात: क्या आप जानते हैं कि कॉलिंग प्रतिबद्ध() स्मृति का उपयोग बढ़ाता है, या इसे कम करता है? – AP257

+2

यह डीबी इंजनों के लिए भी झूठा है जो मायिसम जैसे लेनदेन का समर्थन नहीं करते हैं। चूंकि कोई चल रहा लेनदेन नहीं है, इसलिए खुद को प्रतिबद्धता से अलग करने के लिए फ्लश भी कम है। – underrun

+0

@underrun तो अगर मैं 'session.query()' 'session.flush()' के बाद करता हूं, तो क्या मैं अपने परिवर्तन देखूंगा? यह देखते हुए कि मैं माईसाम का उपयोग कर रहा हूं। –

9

@snapshoe कहते हैं

flush() डेटाबेस

commit() लेन-देन करता है करने के लिए अपने SQL कथन भेजता है।

जब session.autocommit == गलत:

प्रतिबद्ध() फोन करेगा फ्लश() अगर आपके autoflush == यह सच है।

सत्र कब।autocommit == True:

यदि आपने लेनदेन शुरू नहीं किया है तो आप प्रतिबद्ध() को कॉल नहीं कर सकते हैं (जो संभवतः आप नहीं हैं क्योंकि आप शायद इस मोड का उपयोग केवल लेन-देन प्रबंधित करने से बचने के लिए करेंगे)।

इस मोड में आपको अपने ORM परिवर्तनों को सहेजने के लिए फ्लश() को कॉल करना होगा। फ्लश प्रभावी ढंग से आपके डेटा भी करता है।

संबंधित मुद्दे