SQLite Write-Ahead 日志
2013-06-07 13:22 三戒1993 阅读(124) 评论(0) 编辑 收藏 举报默认的方法SQLite 实现原子提交和回滚是回滚日记开始版本370 , 一个新的"Write-Ahead 日志"选项(以下称为"WAL ") 可用
您输入的优点和缺点使用WAL 而不是一个日志回滚优点包括:
- WAL 明显加快在大多数情况下.
- WAL 与读者提供有关并发不会妨碍规格和一个writer 不阻止读者阅读和编写一个同时优化
- 磁盘I/O 的操作sql server 连续使用多WAL.
- WAL 使用大量的更少的fsync( )操作, 因此在麻烦的系统上出现的问题fsync( )系统调用中断时
但是, 您也可以缺点:
- WAL 通常要求VFS 支持shared-memory 原语(异常: WAL 而不共享内存内置unix 和windows )VFSes 支持此但第三方扩展VFSes 为自定义操作系统可能无法.
- 所有进程使用数据库必须在同一主机计算机上;WAL 文件系统在网络上无法使用
- 事务涉及更改对多个ATTACHed 数据库是原子对于每个单独的数据库, 但您没有作为一个原子跨数据库的设置.
- 不能将数据库页大小在输入WAL 模式, 可以为在空数据库或通过使用VACUUM 通过从备份还原的使用备份API 您必须在日记模式以回滚更改页面尺寸
- 不能打开只读WAL 数据库合并进程必须具有写权限"-shm "wal-index 共享内存文件相关联的数据库, 则该文件如果存在, 或者在-i选项指定的目录(如果有写访问的数据库文件如果"-shm ""文件不存在
- WAL 可能非常较快(可能1% 或2% 比传统的rollback-journal 较慢)的方法, 改善它读取的应用程序很少.
- 有一个额外的quasi-persistent "-wal "文件和"-shm 共享内存文件相关联的每个数据库中, 这样可以让SQLite 用作提出申诉更少应用程序file-format .
- 没有足够的磁盘空间额外的操作操作其中, 虽然自动默认情况下, 仍然需要mindful 应用程序开发人员的.
- WAL 工作得最好和更小的事务WAL不作为非常大的交易事务处理大于100 mb .传统的inf 的日记模式可能会更快对于在过量的技嘉事务, WAL 模式可能与一个I/O disk-full 失败错误建议的日记帐分录回滚模式的事务大于概念是一样的兆字节
WAL 如何工作
传统回滚日记通过写入输出的副本works 数据库内容到单独的日志文件然后回滚更改直接到数据库中写入信息在发生崩溃事件或ROLLBACK 包含在回滚, 则原始内容到日志是进行播放要还原该数据库文件到其原始状态"COMMIT 当日志回滚已被删除
反向选择此WAL 方法原始内容保留在数据库中文件并附加到单独的WAL 文件一个COMMIT 当一个特殊的记录, 表示提交将附加到WAL在COMMIT 造成问题的原因可能因此而不曾写入原始数据库这使读者可以从原始要查看连续运行数据库在将更改提交到同时处理的WAL多事务也可以附加到单个WAL 文件末尾
操作
当然, 一个想要最终传输所有交易的附加在WAL 文件复制回原始数据库移动WAL 文件交易回数据库在称为"检查点"
另一种方法是需要关于回滚和windows mobile 设备中心之间的区别在于rollback-journal 方法, 有两种基元中阅读和编写, 而与一个操作, windows mobile 设备中心原语有三种现在的操作: 读取、写入和操作.
默认情况下, 不能SQLite 当WAL 文件达到一个阈值大小为1000 个网页(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 编译时选项用于指定不同的缺省使用WAL )应用程序不必为了执行任何操作对于这些检查点发生但是, 如果他们想查看, 应用程序可以调整检查点的自动阈值也可以关闭自动检查点和检查点期间空闲分钟或在单独的线程或进程
并发
当开始于WAL-mode 数据库读取操作时, 它会记住最后的有效的位置在WAL 提交记录调用此点"end 标记"由于WAL 可以扩大并将新提交记录在各种读者可以连接到该数据库, 每个读取器可能有自己的结尾标记但对于任何特定的读取器结尾标记未改变的事务的持续时间单个读取事务从而确保只将数据库中的内容, 因为它在单个点尺度的时间
当读取器需要一个页面的内容它首先检查WAL 是否已将该页在框中在最后一个副本和它在网页上发生在WAL 阅读器的结尾标记如果没有该页的存在于WAL 阅读器的结尾标记之前, 然后将页面从原始数据库中读取的读者可以存在在单独的进程因此, 若要避免遵循以下每读取器扫描整个WAL 寻找网页(WAL 文件可以增长, 以多种兆字节根据检查点的频率是run)不维护一个名为"wal-index "数据结构共享内存这有助于读者定位如果需要将WAL 快速而且, 最低I/Owal-index 会大大提高服务器的性能读者, 但使用共享内存表示所有读者的同一台机器上必须存在这是为什么windows mobile 设备中心实现将无法正常在网络上的文件系统
尽管只是添加新内容的WAL 文件的结尾由于作家do nothing 干扰操作的读者, 作家和读者可以在同时运行但是, 因为只有一个WAL 文件, 一次只能有一个writer
设置检查点操作从WAL 文件内容并为其返回到原始数据库传输文件设置检查点可以同时运行读者的注意力, 但是必须停止了检查点当它达到一个网页在WAL 过去阅读标记任何当前读卡机在该点处停止当前的新检查点否则可能会将其覆盖数据库的一部分文件当前正在使用检查点会记住(在wal-index )是怎样远得到, 并将继续从WAL 到数据库传输内容来自其在下一个调用
因此一个长时间运行的事务可以防止一个checkpointer 进行读取进度每读取事务最终都会被终止, 但编checkpointer 将能够继续
每当写入操作时发生每页显示多少个的checkpointer writer 检查如果更改和WAL 已传输到数据库和大致如果没有可以防止读者WAL以下是一个将在单独的窗口中运行WAL 回到并开始新的交易报表末尾的WAL这种机制可防止将WAL 文件从成长不绑定
性能注意事项
非常快), 因为它们只涉及写入内容(与两次rollback-journal 事务)和由于写入被所有的顺序进一步同步内容传递到磁盘不是必需的, 只要应用程序, 如果希望sacrifice 持久性, 使用一个断电或软重新引导(作家同步WAL 在每如果事务提交PRAGMA 同步如果被设置为FULL 但省略此sync PRAGMA 同步设置为NORMAL)
在其他手形读取的应用程序要作为随着自WAL 文件的大小每一读取器必须检查WAL 文件的内容, 并检查WAL 文件所需要的时间类似于WAL 文件的大小要使用wal-index 帮助查找WAL 文件中的内容更快, 但仍将关闭使用WAL 文件的大小因此, 要保持良好的性能要保留WAL 文件大小是很重要的按固定间隔通过运行检查点
操作, 因为同步操作.以避免必须是数据库损坏在断电或软重新引导WAL必须同步到持久存储在移动内容, 从WAL 到数据库和文件的数据库必须被重置WAL 同步之前检查点, 还需要有关额外信息checkpointer使到执行任意数量的顺序页写入数据库(页面是可以按降序顺序从WAL 转移给数据库), 但通常, 即使就在该页中写入大量的seek 操作交错这些因素例如检查点不受支持, 订阅服务器.
默认的策略以允许连续写事务增长WAL 直到WAL 变关于1000 个网页在大小然后运行的检查点操作每个后续COMMIT , 直到WAL 被复位为小于1000 个网页默认情况下, 将会自动运行检查点通过使用相同的线程的COMMIT , 把WAL 大小限制此未定义的大多数COMMIT 操作非常快速而导致一个COMMIT (那些以外的一个检查点)慢得多如果该效果将自动配置过程中, 则应用程序也可以禁用自动操作, 并运行该定期检查点在单独的线程, 或独立的过程为命令(链接和接口来完成这个显示如下)
注意, 使用PRAGMA 同步设置为NORMAL, 是检查点操作来颁发一个I/O 屏障或同步操作(在unix fsync( )或FlushFileBuffers() 在windows)如果应用程序因此在单独的线程或进程运行checkpoint主线程或进程上执行数据库查询和更新永远不会阻止同步操作这有助于防止"latch-up "运行在繁忙驱动器应用程序综上所述以不再此配置事务事务, 可能如下回滚电源故障或硬复位
请注意太之间存在多种体系结构, 并折衷考虑了密度的平均读取和写入性能性能要阅读或读取性能, 选择一个想要保持WAL 尽可能小, 因而运行的检查点通常, 可能是每COMMIT要写性能想要amortize 每个检查点的成本最少尽可能多写入这意味着每个希望运行检查点不经常, 并允许WAL 增长, 在每个检查点之前运行检查点的频率值以秒为单位的决策可能会因此而不同应用程序到另一个根据应用程序的相对读和写性能要求默认的策略来运行一次的WAL 达到1000 个网页并设置检查点这个策略似乎没有在工作站上应用程序的测试但是, 其他策略可能会在性能更好地在不同平台上, 或者为不同的工作负载
正在激活和配置WAL 模式
一个SQLite 数据库连接默认值journal_mode=DELETE 要转换为WAL 模式大全 , 请执行下列操作之一:
PRAGMA journal_mode=WAL;
journal_mode 大全 返回一个字符串, 它是新建邮件的模式大全成功时, 将会返回该字符串"wal "如果无法完成转换到WAL (例如, 如果VFS 不支持必要的shared-memory 原语)然后该日志模式将保持不变并将字符串从原语将返回先前的日记模式(例如"删除") .
自动检查点
缺省情况下, SQLite 将自动定检查点的COMMIT 要1000 个网页发生导致WAL 文件或更多的大小, 或当数据库中的最后一个连接文件关闭打开的数据库默认的配置是用来作为大多数应用程序但程序的需要更多的控制强制使用检查点可以使用wal_checkpoint 大全 或通过调用sqlite3_wal_checkpoint( )c接口使用自动检查点阈值可以更改或自动操作可以完全无效, 使用wal_autocheckpoint 大全 或通过调用sqlite3_wal_autocheckpoint( )c接口也可以使用某个程序sqlite3_wal_hook( )要注册回调函数调用脚本命令 当任何事务提交到WAL此回调函数, 然后调用sqlite3_wal_checkpoint( )要为一个基于任何条件它思考是相应的检查点(使用检查点的自动机制都实现为一个简单的周围的包装sqlite3_wal_hook( ))
为同一个WAL 模式
使用"其他日志模式PRAGMA journal_mode=WAL 默认值persistent 显示持久信息如果进程设置WAL 模式, 然后关闭并重新打开数据库, 则该数据库将在WAL 回模式在对比度如果进程设置(例如)PRAGMA journal_mode=TRUNCATE 然后关闭并重新打开数据库将回滚模式的默认设置)下进而备份DELETE 而不是上一个TRUNCATE 设置
WAL 模式意味着应用程序的持久性可以转换为使用SQLite 在WAL 模式下, 不做任何修改应用程序本身一个有歧义以运行"PRAGMA journal_mode=WAL; "在数据库中file(s )命令行shell 或其他实用工具, 然后重新启动该应用程序
将在WAL 日记模式相同的数据库的所有连接文件如果它是设置在任何一个连接.
Read-Only 数据库
没有SQLite 数据库(无论它是WAL 模式)是否可读(如果它位于只读媒体, 它需要恢复因此, 例如, 如果应用程序崩溃SQLite 数据库和示例热日记除非打开进程, 无法打开该数据库具有写入数据库特权文件, 包含数据库文件和目录的热这是因为操作类型无效回滚更改之前必须通过从崩溃添加到数据库中读取并不带可写权限, 无法执行回滚的所有文件和包含它们的目录
在WAL 模式, 您已经打开不能从只读媒体, 因为即使普通在WAL 模式需要recovery-like 操作中读取
高效的实现WAL 读取算法要求有一个哈希表共享内存存在在WAL 文件的内容此散列表被称为网络wal-index wal-index 是否在共享的内存中, 并以enable-psbreakpoint cmdlet 都有一个名称在主机计算机文件系统中自定义VFS 实现免费实现共享内存任何影响请参见匹配, 但其值unix 和windows 驱动程序的内置v6.1.2 SQLite 共享内存使用mmapped 文件使用后缀"命名的-shm "并位于同一个目录数据库文件wal-index都必须已经在第一次访问, 即使按读者, 因此若要打开WAL 数据库, 在"是必需的写权限-shm "共享内存文件 如果该文件已经存在, 否则.将在-i选项指定的目录(如果有需要访问数据库, 以便可以创建wal-index 如果它尚不存在这不会避免产生的自定义VFS 实现的共享内存图形中能够访问.long 类型.只读.WAL 数据库会阻止默认的unix 和windows 的基本WAL 只读媒体上的数据库
因此, 始终应转换为SQLite 数据库PRAGMA journal_mode=DELETE 如下传输到只读媒体
另外, 如果多个进程是访问WAL 模式数据库文件, 然后所有进程都应以使用用户或组的IDs , 使它们写入数据库文件, 将显示"WAL 文件, 共享内存-shm 文件, 并且包含目录
在WAL-Index Shared-Memory 的实现
"wal-index 使用一个普通的中mmapped 稳健性早期("新建快照")实现的WAL 模式中存储wal-index /dev/shm 中所创建volatile shared-memory , 例如文件在linux 或在其他unix 系统上/tmp要使用该方法使用一个不同的root 目录的进程(已更改通过chroot 详细信息)将不同的文件和因此, 使用不同的共享内存区域, 领先的数据库损坏其他严重错误共享内存修改的方法在整个风味的各种不同的unix 块是不可移植的和我们找不到任何方法, 用于创建严重错误共享内存块在windows将我们的唯一方法是.以保证所有过程在访问相同的数据库中找到文件使用同一共享内存的方法是由mmapping 创建共享内存中的一个文件所在的目录数据库本身
使用一个普通的磁盘文件以提供共享内存有弊端是它可能它将共享内存I/O 不必要的磁盘写入到磁盘不过, 开发人员不认为这是一个主要的问题, 因为该wal-index 很少超过32 KiB 选项, 从不同步更多提示, 则wal-index 后备文件被删除如果最后一个表中的连接, 断开, 它将禁止角度的正切磁盘曾发生I/O
专用应用程序路的默认实现共享内存是通过将设计方法VFS 例如如果它是已知的特定数据库会在单个进程内按线索进行访问可以实现wal-index 堆内存, 而不是true 共享内存
使用, 而不会Shared-Memory WAL
开始在SQLite 版本374 , WAL 的数据库可以创建、读取和写入, 即使共享内存不可用, 只要locking_mode 设置为第一个之前, EXCLUSIVE 访问在进程换句话说, 可以WAL 交互的数据库, 而无需使用共享内存如果该过程是线程安全的进程访问数据库此功能允许创建WAL 数据库、读取和写入的传统VFSes 缺乏"version 2"shared-memory 方法xShmMap, xShmLock, xShmBarrier, 和xShmUnmap sqlite3_io_methods 对象的表达式.
如果EXCLUSIVE 锁定模式为第一个WAL-mode 应为数据库访问然后SQLite 永远不会尝试调用任何shared-memory 方法, 因此任何shared-memory wal-index 就曾创建的在这种情况下, 不在当前所选的数据库中仍保留在EXCLUSIVE 模式只要日记模式是WAL; 试图使用"更改的锁定模式PRAGMA locking_mode=NORMAL; "是no-ops将更改, 失败%EXCLUSIVE 锁定的唯一方法是模式是: 首先更改, 失败%WAL 日记模式
如果NORMAL 为第一个WAL-mode 锁定在数据库中访问, 则shared-memory wal-index 被创建这意味着底层VFS 必须支持shared-memory "version 2"如果VFS 不支持shared-memory 方法尝试打开一个microsoft access 数据库已在WAL 模式或数据库的尝试将一个到WAL 模式将失败为long 的连接正在使用shared-memory wal-index , 则可以自由NORMAL 之间的和EXCLUSIVE 更改的锁定模式它只是当shared-memory wal-index 被省略当应EXCLUSIVE 模式锁定第一WAL-mode 数据库访问该系列的模式锁定EXCLUSIVE
向后兼容性
WAL 模式中的sql 文件格式未改变但是, 如果WAL 参数wal-index 新概念和SQLite 更早版本因此, 将不会知道如何从中恢复的狠狠地SQLite 数据库正在工作在WAL 模式如果在发生崩溃防止旧版本的SQLite 试图恢复WAL-mode 数据库(并使坏)在数据库中文件格式(字节18 19 在版本号数据库标题在WAL 模式下)的核心和从1到2因此如果是旧版本的SQLite 将尝试连接到SQLite 工作在WAL 模式的数据库沿直线的"file 它将报告一个错误将不能进行加密或不是数据库"
一个可以显式更改, 失败%WAL 模式使用大全 例如:
PRAGMA journal_mode=DELETE;
xfs 更改超出WAL 模式更改数据库版本的文件格式的数字返回到1旧版本的SQLite 文件可以再次访问数据库