有没有办法从数据库删除对象而不锁定?

时间:2014-01-21 14:41:13

标签: ios objective-c core-data

我有一个具有一对多关系和级联删除规则的对象。删除此对象会启动删除许多相关对象(30 000及更多)。当我在删除后保存上下文时,它会花费不允许的时间(几十秒,也许一分钟)。此外,当我在上下文尚未完成保存时尝试获取某些数据时 - 我得到一个锁。 该应用仅使用一个NSPrivateQueueConcurrencyType的上下文。有没有办法在删除对象后保存上下文,并且能够同时获取数据?是否有任何技术有多个上下文甚至协调员?

1 个答案:

答案 0 :(得分:1)

简短回答:启用WAL,批量保存,并尝试不同的上下文和/或持久性商店协调员。

Core Data中有不同级别的锁。上下文级别存在锁定。如果在多个地方使用上下文,并且一个地方使用上下文,则其他地方等待。有人甚至可能不称它为锁,而只是正常使用上下文。如果上下文是限制(传统)类型,则必须从一个线程或串行队列使用它。所以,连续。如果它在一个队列并发类型上,那些队列也是串行的,只是由Core Data为我们管理。

然后在持久性商店协调员级别上存在锁定。如果两个上下文使用相同的持久性存储协调器,并且一个上下文以需要持久性存储协调器工作的方式使用,则其他上下文将等待。从锁定的角度来看,这比只有一个上下文更有效,但是你需要在上下文之间来回合并数据。

然后锁定数据库文件本身。如果使用了多个持久性存储协调器,并且某些作业需要使用持久性存储,则另一个协调器及其所有上下文都在等待。但如果它不需要商店,他们就不会等待。这是避免锁定的最佳设计,但它也带来了成本。首先,您需要在上下文之间合并更改。但在大多数Core Data应用程序中,这实际上是很平常的事情。但其次,当有两个持久存储协调器时,您有两个独立的缓存。这有时会非常不方便。我甚至会说这是屁股的痛苦。

谈到SQLite,你可以启用WAL,让读者可以与作家同时工作。

Apple还建议您在需要保存大量数据时分批保存。

我个人推荐以下组合。

  1. 在SQLite上启用WAL。
  2. 使用一个持久性商店协调员。
  3. 使用两个上下文来完成不是很大的任务。 “main”是私有队列并发类型。是配置了持久性存储协调器。它允许您进行后台保存,但不允许进行大量数据。第二个上下文将用于UI。它将配置为第一个作为父级和主队列并发类型。
  4. 为大型更新创建其他上下文。使用相同的持久性存储协调器配置它。保存时,分批保存。
  5. 根据需要合并上下文之间的更改。
  6. 使用不同的上下文将允许您不锁定上下文级别。通过使用单个持久性存储协调器,您将从单个缓存中受益。通过启用WAL,您将减少文件级别的锁定。