मेरे पास एक सिस्टम है जो 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 इसे लॉक कर रहा था। मैं समस्या हल करने पर विचार करता हूं, और इससे लिया गया सबक इतना नहीं है कि अगली बार डीबगिंग बेहतर हो।
क्या लेनदेन करें और निष्पादित करें सभी विधियों को अद्यतन करें? – Mark
हां, वे करते हैं। इसके अतिरिक्त, मैंने जांच की है कि शायद कुछ अन्य प्रक्रिया डेटाबेस को लॉक कर रही है (मैंने फ्यूसर का उपयोग किया), लेकिन ऐसा नहीं है। अब तक मैं सिम पर परीक्षण कर रहा हूं, लेकिन अब मैं देखता हूं कि यह आईपॉड टच पर भी काम नहीं करता है, जो एक ही त्रुटि के साथ विफल रहता है। – lawicko
बस जांच रहा है: आपका डेटाबेस एनएफएस-माउंटेड ड्राइव पर संग्रहीत नहीं है, या है ना? – jogojapan