首页 游戏 软件 资讯 排行榜 专题
首页
数据库
SQLite教程(十二):锁和并发控制详解

SQLite教程(十二):锁和并发控制详解

热心网友
11
转载
2026-04-20

一、概述:

要深入理解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。我们下篇再见。

来源:https://www.jb51.net/article/65433.htm
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

XML入门教程:实体-XML/XSLT
前端开发
XML入门教程:实体-XML/XSLT

XML中的实体声明:超越基础的进阶理解 一说起XML的实体,很多人脑子里先蹦出来的可能就是那几个基础的预定义实体,比如 注意看最后的 NDATA a vi。这里的 a vi 并非随意书写,它必须是一个在 NOTATION 中预先声明过的MIME媒体类型标识符。NDATA的作用就是明确告诉处理器:“嘿

热心网友
04.27
XML教程:什么是XML及XML和HTML的区别
前端开发
XML教程:什么是XML及XML和HTML的区别

XML与HTML的本质差异 在深入探讨技术细节前,不妨先明确一个核心概念:XML和HTML虽然长相相似,都使用标签,但它们生来就是为了完成截然不同的任务。理解这一点,是掌握两者关系的关键。 设计初衷:数据内容 vs 数据外观 XML被设计用来描述和携带数据,它的全部焦点在于数据本身的内容和结构。

热心网友
04.27
详细Solaris 11 安装图解教程
系统平台
详细Solaris 11 安装图解教程

Solaris Express Developer Edition:开发者的免费利器 对于想在Solaris平台上进行开发的用户来说,Solaris Express Developer Edition(简称SXDE)无疑是一个绝佳的起点。这个版本完全免费,并保持着每个季度发布一个新版本的节奏,堪称专

热心网友
04.22
windows openclaw安装实录
AI
windows openclaw安装实录

1 环境检查与配置 1) 安装前检查电脑的node配置与nvm配置 万事开头先摸底,动手安装前,最好先确认一下你的电脑环境是否就位。第一步,检查Node js环境是否存在。 打开你的命令行工具,输入: node -v 如果系统已经安装,会立刻显示出版本号,就像这样: 看到版本信息,恭喜,这一关就算

热心网友
04.22
SQLite教程(十二):锁和并发控制详解
数据库
SQLite教程(十二):锁和并发控制详解

一、概述: 要深入理解SQLite数据库的稳定与可靠特性,其核心的锁与并发控制机制是必须掌握的关键。这套机制的具体实现,主要由pager_module模块负责。它如同一位严谨的守护者,严格保障着数据库事务的ACID(原子性、一致性、隔离性、持久性)特性,确保每一次数据操作要么完整提交,要么彻底回滚,

热心网友
04.20

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

Codex实现商业闭环自动盈利模式解析与实战经验分享
AI
Codex实现商业闭环自动盈利模式解析与实战经验分享

开发者Chris通过Codex服务,仅用一句指令便自主完成开源赏金任务,盈利23 68美元,覆盖订阅成本。此事展示AI自主执行商业闭环的潜力,也引发成本与安全争议。AI正从工具向主动创收者转变。

热心网友
05.12
崩坏星穹铁道火花技能详解与效果解析
游戏资讯
崩坏星穹铁道火花技能详解与效果解析

在《崩坏:星穹铁道》的众多角色中,火花以其独特的技能机制,为战斗策略带来了丰富的变数与操作乐趣。她并非单纯的数值输出角色,而是一位集机动性、爆发伤害与战术价值于一体的近战专家。深入理解其技能联动,是充分发挥其战场潜力的关键。 普通攻击 - 迅刃连斩 火花的普通攻击“迅刃连斩”,是一套衔接流畅的近战连

热心网友
05.12
迷你世界智能芯片升级方法详解
游戏资讯
迷你世界智能芯片升级方法详解

想在《迷你世界》中解锁智能芯片的全部潜力?掌握升级方法是关键一步。通过升级,芯片不仅能获得更强大的功能,还能显著提升自动化与创造体验。本指南将为您提供一套清晰、高效的升级方案,助您快速掌握核心技巧。 准备材料:精准收集 成功的升级始于充分的准备。您需要提前备齐以下核心资源:精铁锭、蓝色电能线、硅石以

热心网友
05.12
斗罗大陆猎魂世界寻宝活动玩法全攻略
游戏攻略
斗罗大陆猎魂世界寻宝活动玩法全攻略

《斗罗大陆:猎魂世界》于5月11日至18日限时开启“寻宝之旅”活动。玩家通过任务或礼包获取道具,掷点前进即可领取限定觉醒券、钻石等奖励。完成整圈可得固定资源,累计积分可兑换更多奖励;第16圈起奖励品质提升,整体效率优化。活动门槛低、回报高,无需强制消费,适合各类玩家参与。

热心网友
05.12
燕云十六声龙骧御六合技能详解与角色全解析
游戏攻略
燕云十六声龙骧御六合技能详解与角色全解析

全新秘境“龙骧御六合”开放高难度挑战,玩家需在悬浮石枷上协同维持平衡,应对雷霆与坠石冲击,移动石板可削弱伤害。后续Boss“独夫”登场时,部分队员需切入其内心,其余成员按提示执行阵列动作,全程考验队伍反应与协作能力。

热心网友
05.12