Core Data设置journal_mode为DELETE无效,重启仍生成WAL相关文件
journal_mode=DELETE Isn't Working in Your Core Data App Let’s break down why you’re still seeing *.sqlite-wal and *.sqlite-shm files even after setting journal_mode=DELETE, and how to fix it.
The Root Cause
Your configuration code looks correct on the surface, but there are two common reasons the setting isn’t taking effect:
1. Existing Database Uses WAL Mode (Legacy State)
Core Data defaults to WAL (Write-Ahead Logging) mode starting from iOS 10/macOS 10.12. If your database was originally created with WAL mode (even if you later changed the journal_mode setting), SQLite will retain the existing journal configuration automatically.
The *.sqlite-wal and *.sqlite-shm files are leftover from previous WAL transactions, and SQLite will continue using WAL mode unless you explicitly remove these files and force a mode switch.
2. Your Pragma Setting Isn’t Applied to an Active Connection
While you’re setting the NSQLitePragmaOptions correctly in the store description, if the database connection is already established (or if the WAL files exist), SQLite won’t reapply the journal mode setting automatically.
Step-by-Step Fixes
1. Clear Existing WAL/Shm Files First
Before Core Data loads the persistent store, delete any leftover WAL and shm files to ensure SQLite starts fresh with your desired journal mode. Add this code before you initialize the NSPersistentContainer:
NSURL *sqliteURL = [[self applicationFilesDirectory] URLByAppendingPathComponent:@"My_App.sqlite"]; NSURL *walURL = [sqliteURL URLByAppendingPathExtension:@"wal"]; NSURL *shmURL = [sqliteURL URLByAppendingPathExtension:@"shm"]; NSFileManager *fileManager = [NSFileManager defaultManager]; // Delete WAL file if it exists if ([fileManager fileExistsAtPath:walURL.path]) { NSError *error; if (![fileManager removeItemAtURL:walURL error:&error]) { NSLog(@"Failed to delete WAL file: %@", error); } } // Delete SHM file if it exists if ([fileManager fileExistsAtPath:shmURL.path]) { NSError *error; if (![fileManager removeItemAtURL:shmURL error:&error]) { NSLog(@"Failed to delete SHM file: %@", error); } }
2. Verify the Actual Journal Mode (Not Just Your Settings)
The description.options output shows what you configured, but not what SQLite is actually using. To confirm the active journal mode, execute a PRAGMA journal_mode query after loading the persistent store. Add this code inside your loadPersistentStoresWithCompletionHandler block:
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { if (error != nil) { NSLog(@"Unresolved error %@, %@", error, error.userInfo); abort(); } else { // Check actual journal mode NSManagedObjectContext *context = _persistentContainer.viewContext; [context performBlockAndWait:^{ NSPersistentStoreCoordinator *coordinator = context.persistentStoreCoordinator; for (NSPersistentStore *store in coordinator.persistentStores) { if ([store.type isEqualToString:NSSQLiteStoreType]) { // Debug-only workaround to execute the pragma NSString *pragmaSQL = @"PRAGMA journal_mode;"; NSError *pragmaError = nil; id result = [coordinator executeRequest:[NSClassFromString(@"NSSQLFetchRequest") fetchRequestWithSQLString:pragmaSQL] withContext:context error:&pragmaError]; if (result) { NSLog(@"Actual active journal mode: %@", result); } else if (pragmaError) { NSLog(@"Failed to check journal mode: %@", pragmaError); } } } }]; } }];
Note:
NSSQLFetchRequestis a private API, so only use this for debugging. For production, the first fix should resolve the issue without needing this workaround.
3. Check for iCloud Sync Conflicts
If your app uses Core Data with iCloud sync, WAL mode is mandatory—Core Data will override your journal_mode setting because iCloud relies on WAL for incremental sync. If iCloud is enabled, you won’t be able to disable WAL mode.
Final Notes
After applying these fixes, restart your app. You should no longer see the *.sqlite-wal and *.sqlite-shm files, and the journal mode should show as DELETE in your debug logs.
内容的提问来源于stack exchange,提问作者Max Colla

