Skip to content

Provide a way to disable SQLite journalling mode #411

Closed
sbhklr opened this Issue Feb 12, 2013 · 24 comments

10 participants

@sbhklr
sbhklr commented Feb 12, 2013

Currently MagicalRecord uses the WAL journal_mode when creating an auto migrating store. Since I don't want to use that kind of journal_mode an option for disabling the WAL journal mode would be useful.

@sbhklr sbhklr pushed a commit that referenced this issue Feb 12, 2013
Sebastian Hunkeler Fix for #51 and #411 4b5c8ab
@emeitch
emeitch commented Mar 7, 2013

I get errors at auto migrating when WAL journal_mode is turned on.
But, If I turn off WAL journal_mode, I don't get errors.

So, I wish that you pull this commit.

2013-03-08 00:07:39.966 FooBar[19571:1303] CoreData: annotation: Connecting to sqlite database file at "/var/mobile/Applications/49F76B02-9C41-4A1A-8F20-938599C71906/Library/Application Support/FooBar/FooBar.sqlite"
2013-03-08 00:07:39.970 FooBar[19571:1303] CoreData: sql: pragma journal_mode=WAL
2013-03-08 00:07:39.974 FooBar[19571:1303] CoreData: annotation: Disconnecting from sqlite database due to an error.
2013-03-08 00:07:39.978 FooBar[19571:1303] CoreData: error: (522) I/O error for database at /var/mobile/Applications/49F76B02-9C41-4A1A-8F20-938599C71906/Library/Application Support/FooBar/FooBar.sqlite.  SQLite error code:522, 'not an error'
@blackgold9
Magical Panda Software member
@emeitch
emeitch commented Mar 7, 2013

hmm..

All I can say is the only thing that my errors during migration was solved by switching journal_mode.
Of course, I can not conclude that it is the underlying cause.
However, I think there are ways to cut journal_mode is a good.

@blackgold9
Magical Panda Software member

Is this during an actual migration or when you make a change to the model without a migration and it deletes/replaces the files on disk?

Making WAL turn-offable is probably not horrible, but support should remain.
I've been told by a contact on the Core Data team that most of Apple's own apps on the phone use it, and it brings an appreciable performance boost.

I'd like to figure out what your specific issue is and see if we can address that.
Any chance you can set up a repro-project?

@emeitch
emeitch commented Mar 7, 2013

Is this during an actual migration or when you make a change to the model without a migration and it deletes/replaces the files on disk?

It is an actual migration, not changing to the model without a migration.
So, it is troublesome to reproduce the situation.

I'd like to figure out what your specific issue is and see if we can address that.
Any chance you can set up a repro-project?

Thanks you.
But, the project is private repository.
So, I try to make a small reproducing project.

Please wait.

@mikkelse
mikkelse commented Aug 4, 2013

I have run into the same issue and think I may be able to shed some more light on this:

If you make MagicalRecord set up an automigrating core data stack and you have a mapping model in your project you will experience the 522 I/O error on the sqllite database, because of the WAL mode.

As far as I know even if you set up the store with NSInferMappingModelAutomaticallyOption:YES, core data will still attempt to infer from a custom mapping model if it finds one. I cannot tell you exactly why, but when autoinferring from a custom mapping model, database access will fail if WAL mode is turned on.

This means that while a custom migration should work even when setting up the store for autoinferance, it will fail using MagicalRecord, becuase the convenience method for setting up the automigrating store also sets the WAL jounalling mode.

The solution is to not combine custom migration with magical records automigration in its current implementation, or make a check to make sure WAL mode is only set when core data will not use a custom mapping model.

In my case I thought core data was using autoinferance since I set up the stack with MagicalRecord automigration, but turned out I still had an old tentaive mapping model in my bundle, which i had deleted from the project, but still was part of derived data and thus ended up in the bundle.

Apparently if you delete a mapping model it is not cleared from derived data, which means that even if you have removed it from the project and you are using automigration, core data will still try to infer from it, and with WAL mode turned on this will fail.

@rayray
rayray commented Aug 26, 2013

I can confirm that just adding a usable xcmappingmodel will cause this error. When I commented out the option in MR_autoMigrationOptions, everything worked as expected.

Unfortunate, but I don't think disabling WAL altogether is the appropriate course.

For now, I believe overriding the initial migration process and changing the mode prior to using the mapping model is better, as we get to keep WAL, being preferred by Apple and all.

http://pablin.org/2013/05/24/problems-with-core-data-migration-manager-and-journal-mode-wal/

@blackgold9 I take it your contact hasn't mentioned an error resembling this one, then? I'm unclear if it's a bug with using WAL or simply an expected artifact.

@neilkimmett neilkimmett added a commit to neilkimmett/MagicalRecord that referenced this issue Jan 20, 2014
Sebastian Hunkeler Fix for #51 and #411 77d706e
@tonyarnold tonyarnold closed this Apr 8, 2014
@tonyarnold

I've added options dictionaries to all of the persistent store creation methods in MagicalRecord 3.0. This should let you disable WAL or make any other changes to your stores on init that you'd like to.

@sbhklr
sbhklr commented Apr 14, 2014

Love that. Thank you!

@Spokane-Dude

@tonyarnold Are the "options dictionaries" also in 2.3.0 or just 3.0?

@tonyarnold

@Spokane-Dude: just in 3.0.

I'd like to limit the amount of API change in MagicalRecord 2.3 — big changes belong in the next major version (3.0) 😄

@Spokane-Dude
@tonyarnold

@Spokane-Dude I honestly don't know — the plan was for WWDC, but both Saul and I got really busy with our day jobs and families. We'll put our heads together and come up with a plan.

@Spokane-Dude
@onmyway133

I think if the need is urgent, we can just fork and modify in NSPersistentStoreCoordinator+MagicalRecord.m

@Spokane-Dude
@k06a
k06a commented Oct 16, 2014

Can anyone help me just to change journal_mode to DELETE?
Should I only replace default persistent store?

[MagicalRecord setupCoreDataStack];

id options = @{NSMigratePersistentStoresAutomaticallyOption:@YES,
               NSInferMappingModelAutomaticallyOption:@YES,
               NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
NSPersistentStore *store = [NSPersistentStore MR_defaultPersistentStore];
NSPersistentStore *newStore = [[NSPersistentStore alloc] initWithPersistentStoreCoordinator:[NSPersistentStoreCoordinator MR_defaultStoreCoordinator] configurationName:store.configurationName URL:store.URL options:options];
[NSPersistentStore MR_setDefaultPersistentStore:newStore];

this not works.

@sbhklr
sbhklr commented Oct 18, 2014

@k06a That's how I do it:

SQLiteMagicalRecordStack* _stack = [SQLiteMagicalRecordStack stackWithStoreAtURL:examFileURL model:_managedObjectModel];
_stack.storeOptions = @{NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"}};
[MagicalRecordStack setDefaultStack:_stack];
@k06a
k06a commented Oct 18, 2014

@lightforce who is SQLiteMagicalRecordStack and MagicalRecordStack?
I am using MagicalRecord 2.2, just this way: pod 'MagicalRecord'

@sbhklr
sbhklr commented Oct 20, 2014

@k06a This will not work with MagicalRecord 2.2. You have to upgrade to 3.0.
pod 'MagicalRecord', :git => "https://github.com/magicalpanda/MagicalRecord.git", :branch => "release/3.0"
If you want to do it with MagicalRecord 2.2 you will have to fork it and modify the source code.

@k06a
k06a commented Oct 20, 2014

@lightforce I would like to find any documentation for MR 3.0

@sbhklr
sbhklr commented Oct 20, 2014

@k06a Well, there isn't much documentation available at this moment. Only the code tells the truth. But since this is an open source project you are very welcome to contribute.

@k06a
k06a commented Jan 21, 2015

Here is solution with method swizzling:

#import <JRSwizzle/JRSwizzle.h>

@interface NSPersistentStoreCoordinator (Ext)
+ (NSDictionary *)MR_autoMigrationOptions;
+ (NSPersistentStoreCoordinator *)MR_coordinatorWithSqliteStoreNamed:(NSString *)storeFileName;
+ (NSPersistentStoreCoordinator *)MR_coordinatorWithSqliteStoreNamed:(NSString *)storeFileName withOptions:(NSDictionary *)options;
@end
@implementation NSPersistentStoreCoordinator (Ext)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [NSPersistentStoreCoordinator jr_swizzleClassMethod:@selector(MR_autoMigrationOptions) withClassMethod:@selector(xxx_MR_autoMigrationOptions) error:NULL];
        [NSPersistentStoreCoordinator jr_swizzleClassMethod:@selector(MR_coordinatorWithSqliteStoreNamed:) withClassMethod:@selector(xxx_MR_coordinatorWithSqliteStoreNamed:) error:NULL];
    });
}
+ (NSDictionary *)xxx_MR_autoMigrationOptions {
    NSMutableDictionary *dict = [[[self class] xxx_MR_autoMigrationOptions] mutableCopy];
    dict[NSSQLitePragmasOption] = @{@"journal_mode":@"DELETE"};
    return dict;
}
+ (NSPersistentStoreCoordinator *)xxx_MR_coordinatorWithSqliteStoreNamed:(NSString *)storeFileName {
    id options = @{NSMigratePersistentStoresAutomaticallyOption:@YES,
                   NSInferMappingModelAutomaticallyOption:@YES,
                   NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
    return [self MR_coordinatorWithSqliteStoreNamed:storeFileName withOptions:options];
}
@end

More info about swizzling: http://nshipster.com/method-swizzling/

@aranjan
aranjan commented Apr 18, 2015

Hi, I'm having the same problem with using 2.2 version from pod (also tried using 2.3.0).
Please could some post the changes needed for this. Thanks in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.