SQLite教程(十二):锁和并发控制详解
一、概述:
要深入理解SQLite数据库的稳定与可靠特性,其核心的锁与并发控制机制是必须掌握的关键。这套机制的具体实现,主要由pager_module模块负责。它如同一位严谨的守护者,严格保障着数据库事务的ACID(原子性、一致性、隔离性、持久性)特性,确保每一次数据操作要么完整提交,要么彻底回滚,不留中间状态。此外,该模块还高效地管理着内存缓存,将磁盘文件的数据页缓存在内存中,从而显著提升数据读写效率。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
值得注意的是,pager模块的设计是高度抽象的。它并不处理数据库文件的具体逻辑结构,例如B-Tree、编码格式或索引细节。在pager的视角中,整个数据库文件被简单地视为一系列大小固定(默认通常为1024字节,即1KB)的数据块的集合,每个块被称为一个“页”。页的编号从1开始,直观且连续,1号页即为文件的起始页。
二、文件锁机制详解:
为了实现多进程间的并发访问控制,SQLite设计了一套精密的文件锁状态机。在当前主流版本中,主要定义了五种锁状态,它们构成了协调读写操作的基础框架。
1). UNLOCKED(未锁定):
顾名思义,此状态表示数据库文件当前未被任何进程锁定。这是数据库的初始和空闲状态,任何进程都可以尝试对其进行读取或写入操作。
2). SHARED(共享锁):
当进程需要读取数据时,会获取共享锁。此状态下,数据库处于“只读模式”,允许多个进程同时持有共享锁进行读取,但禁止任何写入操作。只要存在一个有效的共享锁,写操作就必须等待。这是实现高并发读性能的核心。
3). RESERVED(保留锁):
这是一个“写意向锁”。当一个进程主要在读取数据,但已计划在稍后进行写入时,它会先获取一个保留锁。同一时间,一个数据库文件上只能存在一个保留锁,但它可以与多个共享锁共存。这种设计允许“读后写”的事务提前声明意图,避免了部分死锁情况。与Oracle等数据库的细粒度锁(行锁、表锁)相比,SQLite的文件级保留锁对并发性的影响更为显著。
4). PENDING(待定锁):
当持有保留锁的进程准备开始实际写入,但发现仍有其他进程持有共享锁时,它会将锁升级为PENDING状态。此时,写进程必须等待所有现有的读操作完成。关键之处在于,进入PENDING状态后,系统将拒绝新的读请求,以防止写操作被源源不断的读请求“饿死”。待所有现有共享锁释放后,PENDING锁才能进一步升级为排他锁。
5). EXCLUSIVE(排他锁):
这是进行数据写入所必需的终极锁状态。排他锁是独占的,一旦某个进程持有,其他任何类型的锁都无法再获取。因此,为了最大化数据库的并发能力,SQLite会极力优化,尽可能缩短持有排他锁的时间。
必须明确的是,SQLite将所有数据存储于单个文件,并仅提供文件级别的锁,这是一种粗粒度的锁策略。这与MySQL、PostgreSQL等支持行级锁、表级锁的“重量级”关系型数据库在架构上有本质区别。这直接影响了SQLite在高并发写入场景下的扩展性。这并非设计缺陷,而是一种针对嵌入式、轻量级应用场景的权衡。因此,选择合适的数据库时,必须清晰认识SQLite的适用边界。
三、回滚日志与崩溃恢复:
回滚日志是SQLite确保数据一致性与事务原子性的核心安全机制。当一个事务准备修改数据库时,其首要操作并非直接覆盖磁盘数据,而是将待修改页的原始内容完整备份到一个独立的回滚日志文件中。
对于涉及多个数据库文件的事务(ATTACH DATABASE),情况稍复杂:每个被修改的数据库都会生成自己的回滚日志(子日志),同时还会产生一个主日志文件用于全局协调。主日志记录了所有相关子日志的文件名,而每个子日志中也存储了主日志的信息。对于单数据库事务,该位置则为空。
这种日志常被称为“HOT”日志。它之所以“热”,是因为其唯一使命就是在系统崩溃或程序意外退出时,将数据库恢复到事务开始前的一致状态。在事务成功提交的正常流程中,该文件会被删除,仿佛从未存在过。
四、数据写入的完整流程:
下面,我们逐步拆解一个写事务的完整生命周期,看锁、日志与缓存如何协同工作。
准备阶段: 进程首先获取共享锁(SHARED),随即尝试获取保留锁(RESERVED)。保留锁是写入的“准入证”。若获取失败(通常因其他进程已持有),则立即返回SQLITE_BUSY错误。
日志记录: 成功获取保留锁后,进程创建回滚日志文件。在修改内存中的数据页缓存之前,会先将这些页的原始内容完整写入日志文件并同步到磁盘。此时,修改仅发生在内存,磁盘原文件未变,其他进程仍可正常读取。
写入与锁升级: 当缓存满或应用发起提交时,数据需写回磁盘。在此之前,写进程必须确保环境安全:
1. 强制将回滚日志中的所有数据刷入物理磁盘,这是崩溃恢复的保证。
2. 进行锁升级:先获取PENDING锁,再等待并获取排他锁(EXCLUSIVE)。此过程会等待所有现有共享锁释放,并阻止新读请求。
3. 将内存中已修改的“脏页”写回数据库磁盘文件。
若此次写盘仅因缓存满而非事务提交,则排他锁会持续持有。在后续修改新数据页前,需再次将更新的日志内容刷盘。这意味着从第一次刷盘到最终提交前,数据库将对其他所有进程锁定。
事务提交: 当最终提交事务时,流程如下:
4. 确认持有排他锁,且所有内存更改已写入磁盘文件。
5. 再次强制将数据库文件的更改刷入物理磁盘,确保持久化。
6. 关键步骤:删除回滚日志文件。 此操作是事务提交成功的最终标志。若删除前崩溃,下次启动时仍会利用该日志进行恢复。
7. 释放排他锁和PENDING锁。PENDING锁释放后,等待的读进程便可重新进入。
多数据库事务提交: 对于多数据库事务,提交逻辑更严谨:
4. 确保每个数据库均持有排他锁并拥有有效日志。
5. 创建主日志文件,记录所有子回滚日志的文件名。
6. 将主日志文件名回写到每个子日志的指定位置,建立双向关联。
7. 将所有数据库的更改持久化到磁盘。
8. 删除主日志文件(多数据库提交的关键标志)。
9. 删除各个数据库自身的回滚日志文件。
10. 释放所有数据库上的锁。
解决“写饥饿”: SQLite 3.x 版本针对“写饥饿”问题做了重要改进。在SQLite 2.x中,若数据库持续有读操作(共享锁不断),写操作可能永远无法获得锁。SQLite 3引入的PENDING锁机制解决了此问题:当有进程持有PENDING锁时,已存在的读操作可继续完成,但新的读请求会被阻塞。这确保了写操作在现有读操作结束后能获得执行机会。
五、SQL层的事务控制:
SQLite 3将底层锁机制与SQL语言层面的事务语义进行了优雅集成。默认情况下,每条SQL语句都在自动提交模式下运行,执行后立即提交。
当使用BEGIN TRANSACTION显式开启事务后,行为发生变化:BEGIN语句本身并不立即加锁。锁的获取与实际操作绑定——执行第一个SELECT时获取共享锁;执行第一个INSERT/UPDATE/DELETE时获取保留锁;而排他锁仅在提交阶段,数据从内存写入磁盘的短暂瞬间被持有。
一个需要注意的细节是:在同一数据库连接上,如果存在未完成的操作(如一个正在逐行输出结果的SELECT),自动提交会被延迟。即使另一个线程通过该连接执行了写操作,其提交也必须等待之前的读操作完全结束。
至此,关于SQLite核心并发与事务机制的探讨告一段落。本系列的后续内容将聚焦实战,提供具体的编程指南与典型应用示例,帮助您更好地运用SQLite。我们下篇再见。
相关攻略
XML中的实体声明:超越基础的进阶理解 一说起XML的实体,很多人脑子里先蹦出来的可能就是那几个基础的预定义实体,比如 注意看最后的 NDATA a vi。这里的 a vi 并非随意书写,它必须是一个在 NOTATION 中预先声明过的MIME媒体类型标识符。NDATA的作用就是明确告诉处理器:“嘿
XML与HTML的本质差异 在深入探讨技术细节前,不妨先明确一个核心概念:XML和HTML虽然长相相似,都使用标签,但它们生来就是为了完成截然不同的任务。理解这一点,是掌握两者关系的关键。 设计初衷:数据内容 vs 数据外观 XML被设计用来描述和携带数据,它的全部焦点在于数据本身的内容和结构。
Solaris Express Developer Edition:开发者的免费利器 对于想在Solaris平台上进行开发的用户来说,Solaris Express Developer Edition(简称SXDE)无疑是一个绝佳的起点。这个版本完全免费,并保持着每个季度发布一个新版本的节奏,堪称专
1 环境检查与配置 1) 安装前检查电脑的node配置与nvm配置 万事开头先摸底,动手安装前,最好先确认一下你的电脑环境是否就位。第一步,检查Node js环境是否存在。 打开你的命令行工具,输入: node -v 如果系统已经安装,会立刻显示出版本号,就像这样: 看到版本信息,恭喜,这一关就算
一、概述: 要深入理解SQLite数据库的稳定与可靠特性,其核心的锁与并发控制机制是必须掌握的关键。这套机制的具体实现,主要由pager_module模块负责。它如同一位严谨的守护者,严格保障着数据库事务的ACID(原子性、一致性、隔离性、持久性)特性,确保每一次数据操作要么完整提交,要么彻底回滚,
热门专题
热门推荐
开发者Chris通过Codex服务,仅用一句指令便自主完成开源赏金任务,盈利23 68美元,覆盖订阅成本。此事展示AI自主执行商业闭环的潜力,也引发成本与安全争议。AI正从工具向主动创收者转变。
在《崩坏:星穹铁道》的众多角色中,火花以其独特的技能机制,为战斗策略带来了丰富的变数与操作乐趣。她并非单纯的数值输出角色,而是一位集机动性、爆发伤害与战术价值于一体的近战专家。深入理解其技能联动,是充分发挥其战场潜力的关键。 普通攻击 - 迅刃连斩 火花的普通攻击“迅刃连斩”,是一套衔接流畅的近战连
想在《迷你世界》中解锁智能芯片的全部潜力?掌握升级方法是关键一步。通过升级,芯片不仅能获得更强大的功能,还能显著提升自动化与创造体验。本指南将为您提供一套清晰、高效的升级方案,助您快速掌握核心技巧。 准备材料:精准收集 成功的升级始于充分的准备。您需要提前备齐以下核心资源:精铁锭、蓝色电能线、硅石以
《斗罗大陆:猎魂世界》于5月11日至18日限时开启“寻宝之旅”活动。玩家通过任务或礼包获取道具,掷点前进即可领取限定觉醒券、钻石等奖励。完成整圈可得固定资源,累计积分可兑换更多奖励;第16圈起奖励品质提升,整体效率优化。活动门槛低、回报高,无需强制消费,适合各类玩家参与。
全新秘境“龙骧御六合”开放高难度挑战,玩家需在悬浮石枷上协同维持平衡,应对雷霆与坠石冲击,移动石板可削弱伤害。后续Boss“独夫”登场时,部分队员需切入其内心,其余成员按提示执行阵列动作,全程考验队伍反应与协作能力。





