hbase记录日志wal
Write-Ahead Logging has been the default journaling mode for Core Data SQLite stores since iOS 7 and OS X Mavericks. Journaling in Core Data is best explained as the way data transactions are saved into the underlying SQLite store. The WAL mode is significantly faster in most scenarios compared to the previous default “rollback” journal mode and is the underlying reason that makes it possible to have concurrency in Core Data.
自iOS 7和OS X Mavericks起,预写日志记录一直是Core Data SQLite存储的默认日志记录模式。 最好将核心数据中的日记解释为将数据事务保存到基础SQLite存储中的方式。 与以前的默认“回滚”日志记录模式相比,WAL模式在大多数情况下都快得多,这是在Core Data中实现并发的根本原因。
With the WAL mode, Core Data keeps the main SQLite store file untouched and keeps track of data transactions in a -wal
file within the same location of the SQLite store. This means that in some cases, changes are not yet visible in the SQLite store itself. Because of this, you might want to force commit those changes into the SQLite store. In this blog post, I'll give you both an example and an explanation of how you can do this.
在WAL模式下,Core Data保持主SQLite存储文件不变,并在SQLite存储相同位置的-wal
文件中跟踪数据事务。 这意味着在某些情况下,更改尚未在SQLite存储本身中可见。 因此,您可能需要强制将这些更改提交到SQLite存储中。 在此博客文章中,我将为您提供一个示例并说明如何执行此操作。
(How Does Write-Ahead Logging Work?)
You might have always wondered about what those .sqlite-wal
and .sqlite-shm
files meant when you opened up your app's directory to find your Core Data .sqlite
file. Those two files have existed next to your .sqlite
file since iOS 7 and OS X Mavericks, and they are part of the current default Write-Ahead Logging journaling mode of Core Data.
您可能一直想知道打开应用程序目录以查找Core Data .sqlite
文件时这些.sqlite-wal
和.sqlite-shm
文件的含义。 自iOS 7和OS X Mavericks起,这两个文件就.sqlite
文件旁边,它们是Core Data当前默认的Write-Ahead Logging日志记录模式的一部分。
Write-Ahead Logging (WAL) results in multiple database files.
预写日志记录(WAL)导致多个数据库文件。
Journaling modes in Core Data and SQLite prevent data loss by writing new transactions in an in-between journal file. Before WAL was introduced, SQLite was using the traditional rollback journal which works by keeping a copy of the original unchanged database content in the journal file. New changes are written directly into the database file and the journal file is used to roll back changes in the case of a crash. The final commit saving the changes occurs when the rollback journal is deleted.
Core Data和SQLite中的日志记录模式通过在中间的日志文件中写入新的事务来防止数据丢失。 在引入WAL之前,SQLite使用的是传统的回滚日志,其工作原理是将原始未更改的数据库内容的副本保留在日志文件中。 新的更改将直接写入数据库文件,日志文件用于在发生崩溃时回滚更改。 删除回滚日志后,将进行最后一次保存更改的提交。
WAL works in exactly the opposite way. The original content is preserved in the database file and new changes are added into the WAL file. Commits finalizing data changes can actually happen in this WAL file which means that data can be saved while the original database stays untouched. So-called “checkpointing” eventually takes place to transfer all the transactions from the WAL file into the database.
WAL的工作方式正好相反。 原始内容保留在数据库文件中,新的更改添加到WAL文件中。 提交最终确定的数据更改实际上可以在此WAL文件中发生,这意味着可以在不影响原始数据库的情况下保存数据。 最终发生所谓的“检查点”,以将所有事务从WAL文件传输到数据库中。
The .sqlite-shm
file exists as the shared memory between multiple SQLite database connections and it’s used as an index for the WAL file.
.sqlite-shm
文件作为多个SQLite数据库连接之间的共享内存存在,并且用作WAL文件的索引。
You can read the in-depth explanation regarding WAL mode if you like to learn more.
如果您想了解更多信息,可以阅读有关WAL模式的深入说明。
(Core Data Changes Not Visible When Opening an SQLite Database File)
In some cases, you might find yourself opening an SQLite database file and realizing certain changes are missing. This could be caused by the fact that you’ve moved an SQLite file without its matching -wal
and -shm
file. Most database reader apps support WAL mode and automatically show changes that are not yet committed to the SQLite store.
在某些情况下,您可能会发现自己打开SQLite数据库文件并意识到缺少某些更改。 这可能是由于您移动了SQLite文件而不匹配它的-wal
和-shm
文件而-shm
。 大多数数据库阅读器应用程序都支持WAL模式,并自动显示尚未提交到SQLite存储的更改。
(Reasons to force commit changes into the SQLite store)
I bet you wonder why you would want to force commit changes into the SQLite store. It could also be that you ended up in this post because you already have a reason in which case I would love to hear more.
我敢打赌,您想知道为什么要强制将更改提交到SQLite存储中。 也可能是由于您已经有理由在此情况下结束您的发言,在这种情况下,我希望听到更多信息。
The Collect by WeTransfer contains a lot of data and uses Core Data as its storage. Over time, we had to write multiple Core Data migrations, which in rare cases failed with errors like the following:
WeTransfer的Collect包含大量数据,并使用Core Data作为其存储。 随着时间的流逝,我们不得不编写多个Core Data迁移,在极少数情况下,它们会因以下错误而失败:
\“addedDate is a required value.\” UserInfo={NSValidationErrorObject=<NSManagedObject: 0x2819fba70> (entity: ImageContent; id:
\“ additionalDate是必需的值。\” UserInfo = {NSValidationErrorObject = <NSManagedObject:0x2819fba70>(实体:ImageContent; id:
In most cases, you would solve this by writing a correct migration policy that sets the right values during the migration itself. However, we found cases in which we liked to do preprocessing on the local store just before the migration to delete those known invalid cases that were a result of bugs in the past.
在大多数情况下,您可以通过编写正确的迁移策略来解决此问题,该策略会在迁移本身期间设置正确的值。 但是,我们发现了一些案例,在这些案例中,我们希望在迁移之前就在本地存储上进行预处理,以删除由于过去的错误而导致的那些已知无效案例。
Writing the preprocessor was as easy as creating a persistent container using the source database to perform the required transactions. However, in our experience, we found out that those changes were not always visible for the Core Data migration and required us to do a force commit to make sure those changes are applied to the SQLite database file.
编写预处理器就像使用源数据库创建持久容器来执行所需的事务一样容易。 但是,根据我们的经验,我们发现这些更改在Core Data迁移中并不总是可见的,因此要求我们进行强制提交以确保将这些更改应用于SQLite数据库文件。
(How to Force Commit Changes Into the SQLite Database)
Forcing a commit, also known as checkpointing, means merging the transactions that exist in the -wal
file into the store file. By using the traditional rollback journaling mode we can force Core Data to perform a checkpoint operation for Write-Ahead Logging databases.
强制提交(也称为检查点)意味着将-wal
文件中存在的事务合并到存储文件中。 通过使用传统的回滚日志记录模式,我们可以强制Core Data对预写日志记录数据库执行检查点操作。
To do this, we can add a persistent store by setting the journal mode to DELETE
:
为此,我们可以通过将日志模式设置为DELETE
来添加持久存储:
private func forceWALCheckpointingForStore(at storeURL: URL, model: NSManagedObjectModel) throws {
do {
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
let options = [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
let store = try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
try persistentStoreCoordinator.remove(store)
} catch let error {
throw Error.forcedWALCheckFailed(error: error)
}
}
This method takes the source store URL and database model as input and is enough to force commit the changes into the local database file.
此方法将源存储URL和数据库模型作为输入,并且足以强制将更改提交到本地数据库文件中。
在NSPersistentContainer中完全禁用WAL模式 (Disabling WAL Mode Completely in an NSPersistentContainer)
If you like to write changes directly into the SQLite file you can decide to directly commit changes into the local SQLite file by setting up your persistent container with the rollback journaling mode:
如果您想将更改直接写到SQLite文件中,则可以通过使用回滚日志记录模式设置持久性容器来决定将更改直接提交到本地SQLite文件中:
let persistentContainer = NSPersistentContainer(name: "Database_Name", managedObjectModel: model)
let storeDescription = NSPersistentStoreDescription(url: storeURL)
storeDescription.setValue("DELETE" as NSObject, forPragmaNamed: "journal_mode")
persistentContainer.persistentStoreDescriptions = [storeDescription]
(Verifying the Configured Journal Mode Using SQLite Debugging)
Although this section is best explained in my detailed Core Data Debugging post, there’s one launch argument I’d like to highlight. By using -com.apple.CoreData.SQLDebug 4
as an argument passed on launch you will get detailed information on the transactions happening in Core data.
尽管在我详细的Core Data Debugging文章中最好地解释了本节,但我想强调一个启动参数。 通过使用-com.apple.CoreData.SQLDebug 4
作为启动时传递的参数,您将获得有关Core数据中发生的事务的详细信息。
Within those logs you’ll find the following information regarding the journal mode:
在这些日志中,您将找到有关日记模式的以下信息:
CoreData: sql: pragma journal_mode=DELETE
(What to Do When the Delete Journal Mode Is Resulting in a Deadlock)
A deadlock can occur if a persistent container with a different journaling mode is currently active and using the database file. I don’t have an exact explanation for why this happens, but it’s likely caused by an active lock on the database files. Therefore, make sure to only force commit when there are no active connections to your database.
如果当前处于活动状态且使用其他日志记录模式的持久性容器正在使用数据库文件,则会发生死锁。 对于这种情况的发生,我没有确切的解释,但这很可能是由于主动锁定数据库文件引起的。 因此,请确保仅在没有活动的数据库连接时才强制提交。
(Conclusion)
Core Data allows us to save data in an SQLite store using high-level APIs. After reading this blog post, you hopefully learned more about the underlying structure, which is using the Write-Ahead Logging journaling mode. Force commits allow you to write changes into the SQLite file to make sure changes actually exist in the local database file. If you’d like to improve your Swift knowledge even more, check out the Swift category page.
核心数据允许我们使用高级API将数据保存在SQLite存储中。 阅读此博客文章后,您希望了解更多有关底层结构的信息,该底层结构正在使用Write-Ahead Logging日记记录模式。 强制提交使您可以将更改写入SQLite文件,以确保更改确实存在于本地数据库文件中。 如果您想进一步提高Swift知识,请查看Swift类别页面。
Thanks!
谢谢!
hbase记录日志wal