sqlite3 第五章-事务、调整页面缓存、等待锁、代码
事务
一、事务生命周期
- 何时开始?何时结束?
在任何时候,只在一个事务下执行一个连接。
- 何时开始影响其他连接?
自动提交模式下,每发一个命令就运行一个单独的事务;发出begin命令时,直到COMMIT或rollback,为一个事务。
二、锁状态
UNLOCK、PENDING、SHARED、RESERVED都可在同一时间同一数据库的不同连接中存在。
EXCLUSIVE:排他锁
锁到事务结束或系统崩溃时,才会释放。
三、读事务
以两次select操作为例。
- 显示事务只锁定一次,且能确认两次查询结果一致。
- 隐式事务会锁定两次,且无法保证两次结果一致。
四、写事务
1、保留状态
准备写入时,必须从共享锁转换到保留锁。
此时的修改存储在本地pager内的内存缓存中。
pager管理的三种页面:
已修改页:B-tree已改变记录的页。
未修改页:B-tree读取但并未改变的页。
日志页:B-tree修改前会将其原始页写入日志。
编译选项cache_size可配置缓存。
2、待定状态
待定锁的作用是阻止其他连接获取待定锁。等待其他连接释放其共享锁,数据库就可进行写操作了。pager从待定状态装换到独占状态。
3、独占状态
主要工作是将修改的页面缓存刷新至数据库文件中。
刷新策略通过编译指示synchronous设置。
事务提交后,pager清理日志,清理页缓存,从独占锁回到未锁定状态。
4、自动提交与效率
显示事务效率和安全性更高。
调整页面缓存
一、过渡到独占状态
sqlite3有可能由于页面缓存满而被迫进入独占状态。
对于页面缓存满的情况,sqlite存在软限制。即由于缓存是已修改项和未修改页的混合。此时,pager将试图消除页面缓存,将未修改页清除。缓存满后,再次重复以上过程。直至缓存被修改页填满,只能进入独占状态。
应尽量提供大的缓存,以提高整体并发性。
二、调整页面缓存
可用sqlite3_analyzer工具对数据表进行分析。
三、等待锁
对应处理无法获取共享锁(返回SQLITE_BUSY)的情况。
可通过注册繁忙处理程序或调用sqlite3_busy_timeout()处理上述问题。
调用sqlite3_busy_timeout(),只是消磨时间等待。pager自动处理此过程,休眠时间到,返回SQLITE_BUSY。