sqlite之WAL模式
- 概述
在3.7.0以后,WAL(Write-Ahead Log)模式可以使用,是另一种实现事务原子性的方法。- WAL的优点
- 在大多数情况下更快
- 并行性更高。因为读操作和写操作可以并行。
- 文件IO更加有序化,串行化(more sequential)
- 使用fsync()的次数更少,在fsync()调用时好时坏的机器上较为未定。
- 缺点
- 一般情况下需要VFS支持共享内存模式。(shared-memory primitives)
- 操作数据库文件的进程必须在同一台主机上,不能用在网络操作系统。
- 持有多个数据库文件的数据库连接对于单个数据库时原子的,对于全部数据库是不原子的。
- 进入WAL模式以后不能修改page的size。
- 不能打开只读的WAL数据库(Read-Only Databases),这进程必须有"-shm"文件的写权限。
- 对于只进行读操作,很少进行写操作的数据库,要慢那么1到2个百分点。
- 会有多余的"-wal"和"-shm"文件
- 需要开发者注意checkpointing
- WAL的优点
原理
回滚日志的方法是把为改变的数据库文件内容写入日志里,然后把改变后的内容直接写到数据库文件中去。在系统crash或掉电的情况下,日志里的内容被重新写入数据库文件中。日志文件被删除,标志commit着一次commit的结束。
WAL模式于此此相反。原始为改变的数据库内容在数据库文件中,对数据库文件的修改被追加到单独的WAL文件中。当一条记录被追加到WAL文件后,标志着一次commit的结束。因此一次commit不必对数据库文件进行操作,当正在进行写操作时,可以同时进行读操作。多个事务的内容可以追加到一个WAL文件的末尾。
- checkpoint
最后WAL文件的内容必须更新到数据库文件中。把WAL文件的内容更新到数据库文件的过程叫做一次checkpoint。
回滚日志的方法有两种操作:读和写。WAL有三种操作,读、写和checkpoint。
默认的,SQL会在WAL文件达到1000page时进行一次checkpoint。进行WAL的时机也可以由应用程序自己决定。 - 并发性
当一个读操作发生在WAL模式的数据库上时,会首先找到WAL文件中最后一次提交,叫做"end mark"。每一个事务可以有自己的"end point",但对于一个给定额事务来说,end mark是固定的。
当读取数据库中的page时,SQLite会先从WAL文件中寻找有没有对应的page,从找出离end mark最近的那一条记录;如果找不到,那么就从数据库文件中寻找对一个的page。为了避免每次事务都要扫描一遍WAL文件,SQLite在共享内存中维护了一个"wal-index"的数据结构,帮助快速定位page。
写数据库只是把新内容加到WAL文件的末尾,和读操作没有关系。由于只有一个WAL文件,因此同时只能有一个写操作。
checkpoint操作可以和读操作并行。但是如果checkpoint把一个page写入数据库文件,而且这个page超过了当前读操作的end mark时,checkpoint必须停止。否则会把当前正在读的部分覆盖掉。下次checkpoint时,会从这个page开始往数据库中拷贝数据。
当写操作时,会检查WAL文件被拷贝到数据库的进度。如果已经完全被拷贝到数据库文件中,已经同步,并且没有读操作在使用WAL文件,那么会把WAL文件清空,从其实开始追加数据。保证WAL文件不会无限制增长。 - 性能
写操作是很快的,因为只需要进行一次写操作,并且是顺序的(不是随机的,每次都写到末尾)。而且,把数据刷到磁盘上是不必须的。(如果PRAGMA synchronous是FULL,每次commit要刷一次,否则不刷。)
读操作的性能有所下降,因为需要从WAL文件中查找内容,花费的时间和WAL文件的大小有关。wal-index可以缩短这个时间,但是也不能完全避免。因此需要保证WAL文件的不会太大。
为了保护数据库不被损坏,需要在把WAL文件写入数据库之前把WAL文件刷入磁盘;在重置WAL文件之前要把数据库内容刷入数据库文件。此外checkpoint需要查找操作。这些因素使得checkpoint比写操作慢一些。
默认策略是很多线程可以增长WAL文件。把WAL文件大小变得比1000page大的那个线程要负责进行checkpoint。会导致绝大部分读写操作都是很快的,随机有一个写操作非常慢。也可以禁用自动checkpoint的策略,定期在一个线程或进程中进行checkpoint操作。
高效的写操作希望WAL文件越大越好;高效的读操作希望WAL文件越小越好。两者存在一个tradeoff。
- checkpoint
激活和配置WAL模式
PRAGMA journal_mode=WAL;,如果成功,会返回"wal"。自动checkpoint
可以手动checkpointsqlite3_wal_checkpoint(sqlite3 *db, const char *zDb)
配置checkpoint
sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
Application-Initiated Checkpoints
可以在任意一个可以进行写操作的数据库连接中调用sqlite3_wal_checkpoint_v2()或sqlite3_wal_checkpoint()。WAL模式的持久性
当一个进程设置了WAL模式,关闭这个进程,重新打开这个数据库,仍然是WAL模式。
如果在一个数据库连接中设置了WAL模式,那么这个数据库的所有连接都将被设为WAL模式。
只读数据库
如果数据库需要恢复,而你只有读权限,没有写权限,那么你不能读取这个数据库,因为进行读操作的第一步就是恢复数据库。
类似的,因为WAL模式下的数据库进行读操作时,需要类似数据库恢复的操作,因此如果只有读权限,也不能对打开数据库。
WAL的实现需要有一个基于WAL文件的哈希表在共享内存中。在Unix和Windows的VFS实现中,是基于MMap的。将共享内存映射到同目录下的"-shm"文件中。因此即使是对WAL模式下的数据库文件进行读操作,也需要写权限。
为了把数据库文件转化为只读的文件,需要先把这个数据库的日志模式改为"delete".避免过大的WAL文件
WAL-index的共享内存实现
在WAL发布之前,曾经尝试过将wal-index映射到临时目录,如/dev/shm或/tmp。但是不同的用户看到的目录是不同的,所以此路不通。
后来尝试将wal-index映射到匿名的虚拟内存块中,但是无法在不用的Unix版本中保持一致。
最终决定采用将wal-index映射到同目录下。这样子会导致不必要的磁盘IO。但是问题不大,是因为wal-index很少超过32k,而且从不会调用sync操作。此外,最后一个数据库连接关闭以后,这个文件会被删除。
如果这个数据库只会被一个进程使用,那么可以使用heap memory而不是共享内存。不用共享内存实现WAL
在3.7.4版本以后,只要SQLite的lock mode被设为EXCLUSIVE,那么即使共享内存不支持,也可以使用WAL模式。
换句话说,如果只有一个进程使用SQLite,那么不用共享内存也可以使用WAL。
此时,将lock mode改为normal是无效的,需要实现取消WAL模式。
sqlite之WAL模式的更多相关文章
- GRDB使用SQLite的WAL模式
GRDB使用SQLite的WAL模式 WAL全称是Write Ahead Logging,它是SQLite中实现原子事务的一种机制.该模式是从SQLite 3.7.0版本引入的.再此之前,SQLi ...
- SQLite 的 CodeFirst 模式
目录 问题描述 解决方案 安装依赖包 修改程序配置 App.config 创建模型对象 Person.cs 创建数据上下文 PersonDbContext.cs 主程序调用 Program.cs 注意 ...
- SQLite的WAL机制
标注:本文部分有黏贴这里的资料,另外还加了一些自己的笔记 使用CoreData或者SQLite3的时候,我们创建的数据库, 在存储的文件夹中有三个文件:分别为:**.sqlite **.sqlite ...
- 【腾讯Bugly干货分享】微信iOS SQLite源码优化实践
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58022433221be01499480 作者:张三华 前言 随着微信iO ...
- SQLiteOpenHelper/SQLiteDatabase/Cursor源代码解析
转载请注明出处:http://blog.csdn.net/y_zhiwen/article/details/51583188 Github地址.欢迎star和follow 新增android sqli ...
- Sqlite学习笔记(三)&&WAL性能测试
WAL是SQLite3.7.0版本引入的一个重大改进.SQLite官网宣称在很多使用场景下,WAL模型的性能都要好于默认的DELETE模式.下面将针对几个主要场景对WAL性能做测试,测试的硬件与xxx ...
- 浅析SQLite的锁机制和WAL技术
锁机制 SQLite基于锁来实现并发控制.SQLite的锁是粗粒度的,并不拥有PostgreSQL那样细粒度的行锁,这也使得SQLite较为轻量级.当一个连接要写数据库时,所有其它的连接都被锁住,直到 ...
- 【原创】System.Data.SQLite内存数据库模式
对于很多嵌入式数据库来说都有对于的内存数据库模式,SQLite也不例外.内存数据库常常用于极速.实时的场景,一个很好的应用的场景是富客户端的缓存数据,一般富客户端的缓存常常需要分为落地和非落地两种,而 ...
- SQLite学习笔记(六)&&共享缓存
介绍 通常情况下,sqlite中每个连接都会一个独立的pager对象,pager对象中管理了该连接的缓存信息,通过pragma cache_size指令可以设置缓存大小,默认是2000个page,每个 ...
随机推荐
- javaccript学习1
1.javascript中的三种消息框 (1)警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行操作. 语法: alert("文本" ...
- NET中验证控件表达式汇总
ASP.NET为开发人员提供了一整套完整的服务器控件来验证用户输入的信息是否有效.这些控件如下: 1.RequiredFieldValidator:验证一个必填字段,如果这个字段没填,那么,将不能提交 ...
- Theano入门神经网络(四)
这一部分主要介绍用Theano 实现softmax函数. 在多分类任务中经常用到softmax函数,首先上几个投影片解释一下 假设目标输出是y_hat ,激活函数后的Relu y 一个是1.2 一个是 ...
- express 框架之session
一.什么是session? 最近在学习node.js 的express框架,接触到了关于session方面的内容.翻阅了一些的博客,学到了不少东西,发现一篇博文讲的很好,概念内容摘抄如下: Sessi ...
- 基于 CSS3 Media Queries 的 HTML5 应用
先来介绍下 media,确切的说应该是 CSS media queries(CSS 媒体查询),媒体查询包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3 ...
- qml基础学习 Canvas画笔
一.画布元素 自qt4.7发布qml以来,qml也在一直不断的完善中,在qt4时代使用qml时如果需要异形图,那我们只能让设计师来切图,这样的感觉是很不爽的,总感觉开发没有那么犀利.但是到了qt5这一 ...
- Ajax学习记录
Ajax 1:ajax是一种页面局部刷新的技术,不是整个页面刷新.这里就像论坛评论里面的刷新,只是局部的,不是页面全部提交到服务器. 2:页面不刷新,创建个WebClient,它和服务器进行交互.&l ...
- 为html.EditorFor添加样式
有网友问及,怎样为html.EditorFor添加样式. 解决方法,可以参考下面语法: 先new一个htmlAttributes. @model Book @using Insus.NET.Model ...
- Bootstrap学习笔记系列7-----Bootstrap简单背景CSS及其他辅助类
背景 通过添加下列类,可以快捷的变换背景颜色,如果是链接的话,鼠标移动上去会变暗 bg-primary 被修饰元素将会应到primary类,显示吃淡蓝色,文本颜色会变成白色. bg-success 被 ...
- sql server删除默认值(default)的方法
不废话了----- 例如要删除student表的sex默认值 sp_help student;查询结果 找到constraiont_name的对应的值 最后 ALTER TABLE student D ...