2012-01-11 13 views
6

मेरे पास एक सिस्टम है जो SQLite डेटाबेस पर आधारित है। प्रत्येक क्लाइंट के पास स्थानीय डेटाबेस होता है, और एक बार थोड़ी देर में अपडेट मुख्य सर्वर से आता है, बस एक छोटी डेल्टा। डीबी फ़ाइल। कार्य डेल्टा फ़ाइल के साथ स्थानीय डेटाबेस में विलय करना है, स्कीमा दोनों में समान है।SQLite डेटाबेस को अलग करते समय त्रुटि - डेटाबेस लॉक किया गया है

मेरे डेटाबेस प्रबंधन के लिए मैं fmdb wrapper का उपयोग करता हूं जो here पाया जा सकता है। मुख्य धागे में, मैं कनेक्शन को स्थानीय डेटाबेस में खोलता रहता हूं। डेल्टा फ़ाइल पृष्ठभूमि में आती है, और मैं किसी भी उपयोगकर्ता इंटरफ़ेस से बचने के लिए पृष्ठभूमि में विलय करना चाहता हूं जिससे यह हो सकता है।

विलय के लिए ही, एकमात्र विकल्प जो मैंने पाया वह स्थानीय डेटाबेस में डेल्टा डेटाबेस संलग्न करना है, फिर पंक्तियों को सम्मिलित/अद्यतन करें, और अंततः डेल्टा को अलग करें। यह अपेक्षाकृत चिकनी काम नहीं करता है जैसा कि मैंने उम्मीद की थी।

कोड विवरण:

  • onDeltaGenerated विधि एक पृष्ठभूमि धागा जब भी डेल्टा डेटाबेस संसाधित करने के लिए तैयार है (सर्वर से आता है और पठनीय स्थान में सहेजा जाता है) में शुरू हो जाती है।
  • डेल्टा डीबीपीथ फाइल सिस्टम में डेल्टा डेटाबेस का पूर्ण स्थान है।
  • डीबी परिवर्तनीय संदर्भ FMDataBase कनेक्शन खोलें।

कोड:

- (void)onDeltaGenerated:(NSNotification*)n { 
NSString* deltaDBPath = [[n userInfo] objectForKey:@"deltaPath"]; 
@synchronized(db) { 
    [db executeUpdate:@"ATTACH DATABASE ? AS delta", deltaDBPath]; 
    if ([db hadError]) { 
     NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]); 
    } else { 
     NSLog(@"Delta attached from %@", deltaDBPath); 
    } 
    [db beginTransaction]; 
    BOOL update1 = NO; 
    BOOL update2 = NO; 
    BOOL transaction = NO; 
    update1 = [db executeUpdate:@"INSERT OR REPLACE INTO equipment SELECT * FROM delta.equipment"]; 
    if (!update1) { 
     NSLog(@" *** ERROR *** update 1 failed!"); 
     NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]); 
    } 
    update2 = [db executeUpdate:@"INSERT OR REPLACE INTO equipmentExt SELECT * FROM delta.equipmentExt"]; 
    if (!update2) { 
     NSLog(@" *** ERROR *** update 2 failed!"); 
     NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]); 
    } 
    transaction = [db commit]; 
    if (!transaction) { 
     NSLog(@" *** ERROR *** transaction failed!"); 
     NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]); 
    } 
    [db executeUpdate:@"DETACH DATABASE delta"]; 
    if ([db hadError]) { 
     NSLog(@" ****ERROR*** %d: %@", [db lastErrorCode], [db lastErrorMessage]); 
    } else { 
     NSLog(@"Delta detached"); 
    } 
} 

}

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

2012-01-11 12:08:52.106 DBApp[1415:11507] Error calling sqlite3_step (1: SQL logic error or missing database) SQLITE_ERROR 
2012-01-11 12:08:52.107 DBApp[1415:11507] DB Query: DETACH delta 
2012-01-11 12:08:52.107 DBApp[1415:11507] ****ERROR*** 1: database delta is locked 

मैं भी यही करने के लिए, लेकिन लेन-देन में आवेषण डाले बिना की कोशिश की, परिणाम समान है। एक और बात @ सिंक्रनाइज़ क्लॉज को हटाना था, लेकिन कोई किस्मत भी नहीं थी। मेरा अनुमान है कि पृष्ठभूमि थ्रेड से स्थानीय डेटाबेस कनेक्शन तक पहुंचने का प्रयास करते समय विफल रहता है, लेकिन फिर यह संलग्न करने और सम्मिलित करने के लिए कैसे प्रबंधित होता है? किसी भी मदद की सराहना की।

संपादित

मैं मुख्य थ्रेड पर कोड ले जाया गया, तो db अब केवल मुख्य थ्रेड से पहुँचा है। समस्या बनी हुई है।

EDIT2

ठीक है, तो सब कुछ कोशिश कर के बाद, मैं एक पल के लिए इस पर छोड़ दिया और फिर वापस आया जब पहले उत्तर यहाँ दिखाई दिया। हैरानी की बात है, सबकुछ ठीक काम करता प्रतीत होता है, इसलिए मेरा कोड सही होना चाहिए। मुझे संदेह है कि फ़ाइल को लॉक करने वाले विभिन्न थ्रेडों के साथ यह समस्या थी, क्योंकि मैंने एक्सकोड, SQLiteDatabaseBrowser और डेटाबेस खोलने के लिए मेरे एप्लिकेशन का उपयोग किया था। भले ही lsof ने दिखाया कि फ़ाइल लॉक नहीं हुई थी, मुझे लगता है कि यह गलत था और या तो XCode या SQLiteDatabaseBrowser इसे लॉक कर रहा था। मैं समस्या हल करने पर विचार करता हूं, और इससे लिया गया सबक इतना नहीं है कि अगली बार डीबगिंग बेहतर हो।

+0

क्या लेनदेन करें और निष्पादित करें सभी विधियों को अद्यतन करें? – Mark

+0

हां, वे करते हैं। इसके अतिरिक्त, मैंने जांच की है कि शायद कुछ अन्य प्रक्रिया डेटाबेस को लॉक कर रही है (मैंने फ्यूसर का उपयोग किया), लेकिन ऐसा नहीं है। अब तक मैं सिम पर परीक्षण कर रहा हूं, लेकिन अब मैं देखता हूं कि यह आईपॉड टच पर भी काम नहीं करता है, जो एक ही त्रुटि के साथ विफल रहता है। – lawicko

+0

बस जांच रहा है: आपका डेटाबेस एनएफएस-माउंटेड ड्राइव पर संग्रहीत नहीं है, या है ना? – jogojapan

उत्तर

1

बस जांच रहा है - क्या NSLog(@"Delta attached from %@", deltaDBPath); सफलतापूर्वक मुद्रित हो जाता है, और इसके बाद आप जिन त्रुटियों का वर्णन करते हैं, उसके बाद क्या होता है?


लाइन Error calling sqlite3_step (1: SQL logic error or missing database) SQLITE_ERROR शायद गौर करने के सबसे दिलचस्प बिट होने जा रहा है।

कुछ गुगलिंग के बाद, एक मुद्दा जो आता है वह डेटाबेस फ़ाइल लिखने योग्य नहीं हो सकता है। http://www.iphonedevsdk.com/forum/iphone-sdk-development/20142-problem-insert-fmdb.html

मुख्य डीबी आप को अपडेट कर रहे एप्लिकेशन के बंडल के भीतर है, तो आप इसे संशोधित करने की अनुमति नहीं कर रहे हैं - आप पहली Documents या अन्य लिखने योग्य निर्देशिका में एक प्रतिलिपि बनाने चाहिए।


त्रुटि वास्तव में होने वाली है जब आप कोशिश करते हैं और अलग है, या यह वास्तव में हो रहा है जब आप कोशिश करते हैं और INSERT OR REPLACE लेनदेन प्रदर्शन है?

क्या आप इन बयानों के बाद सुनिश्चित करने के लिए if ([db hadError]) {… डाल सकते हैं?

+0

हाय, इसे देखने के लिए समय निकालने के लिए धन्यवाद। मैंने अपना कोड अपडेट किया ताकि मैं त्रुटि को आसानी से पकड़ सकूं। इस पंक्ति के लिए त्रुटि आई: '[डीबी executeUpdate: @ "डेटा डाटाबेस डेल्टा"]; '। डेटाबेस लिखने योग्य है। मैंने कोड फिर से चलाया और यह ठीक काम करता है! मैं इसे और अधिक परीक्षण करने जा रहा हूं और अगर कुछ भी नहीं आता है तो कोई जवाब नहीं आता है या यदि कोई भी इस बारे में अधिक विशिष्ट विचार के साथ आता है कि यह क्या हो सकता है। धन्यवाद! – lawicko

1

आप पहले से ही

[db open]; 
कहीं

किया था?

+0

निश्चित रूप से, मैंने किया। अन्यथा यह बहुत शुरुआत में असफल हो जाएगा। – lawicko

1

क्या आप वाकई सभी प्रश्नों को डीबी में रीसेट कर चुके हैं? सुनिश्चित करें कि आप sqlite3_reset(stmt) कॉल करें।

+0

दुर्भाग्यवश मेरे पास मूल कोड तक पहुंच नहीं है, लेकिन जैसा कि मैंने संपादन में लिखा है, ऐसा लगता है कि यह एक समय की समस्या है जो जादुई रूप से गायब हो गई है, और हमें इसके साथ कोई और समस्या नहीं है। लेकिन प्रतिक्रिया के लिए धन्यवाद, मुझे यकीन है कि डेटाबेस वापस लॉक होने पर मुझे वापस आना होगा! – lawicko

0

यहां एक है जो मुझे थोड़ा (मुझे पता है): मैं एक नई सुविधा बनाने के दौरान परीक्षण (बहुत अधिक, ऐसा लगता है) परीक्षण कर रहा था जिसके लिए एक अतिरिक्त ATTACHed डेटाबेस (.NET में, मार्ग)। तो मैं

var i = query.ExecuteNonQuery("ATTACH DATABASE @FilePath AS `MergeDestination`;", fullPath); 
FakeCallThatDoesNothing() 
var i = query.ExecuteNonQuery("DETACH DATABASE `MergeDestination`;"); 

जो, appearently, लगाव ज्यादा सिर scratching में जगह और परिणाम लेने के लिए के लिए पर्याप्त समय की अनुमति नहीं है।

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