深入理解SQLite:存储引擎、索引、事务与锁

文章目录

    • 一、存储引擎
    • 二、索引的数据结构和类型
      • 2.1 B-Tree
      • 2.2 其他类型的索引
      • 2.3 小结
    • 三、事务处理中的一致性问题
      • 3.1 脏读(Dirty Read)
      • 3.2 不可重复读(Non-repeatable Read)
      • 3.3 幻读(Phantom Read)
      • 3.4 小结
    • 四、事务隔离级别和MVCC实现
      • 4.1 串行化(SERIALIZABLE)
      • 4.2 可重复读(REPEATABLE READ)
      • 4.3 小结
    • 五、锁的类型和级别
      • 5.1 未锁定(UNLOCKED)
      • 5.2 共享(SHARED)
      • 5.3 保留(RESERVED)
      • 5.4 挂起(PENDING)
      • 5.5 排他(EXCLUSIVE)
      • 5.6 锁定级别的转换关系
    • 六、总结

SQLite是一款轻量级的数据库,广泛应用于各种软件和系统中。本文将深入探讨SQLite的存储引擎、索引、事务隔离级别、MVCC实现以及锁的类型和级别。

一、存储引擎

SQLite使用一种称为B-Tree的数据结构作为其存储引擎。B-Tree可以高效地插入、删除和查找数据,因此非常适合用作数据库的存储引擎。

二、索引的数据结构和类型

2.1 B-Tree

SQLite的索引也使用B-Tree数据结构。索引可以大大提高查询的速度,因为它可以让数据库快速找到满足查询条件的数据。B-Tree是一种自平衡的树结构,它可以保持数据有序,且在插入、删除和查找等操作中具有较高的效率。以下是为什么SQLite选择B-Tree作为索引数据结构的原因:

  1. 查询效率:B-Tree的查找效率非常高。在最坏情况下,B-Tree的查找时间复杂度为O(log N),其中N是存储在树中的键的数量。这意味着,即使索引中有大量数据,B-Tree也可以快速找到满足查询条件的数据。

  2. 插入和删除效率:B-Tree在插入和删除操作中也具有较高的效率。当插入或删除数据时,B-Tree可以自动调整其结构以保持平衡,并确保操作的时间复杂度为O(log N)。这使得B-Tree成为动态修改数据的理想选择。

  3. 有序存储:B-Tree可以保持数据有序,这意味着当执行范围查询或排序操作时,B-Tree可以直接返回有序的数据,无需额外的排序操作。

  4. 磁盘友好:B-Tree数据结构非常适合磁盘存储。由于B-Tree可以将相关数据存储在相邻的磁盘块中,因此可以减少磁盘I/O操作,从而提高查询性能。

由于上述优点,B-Tree成为了SQLite索引的理想数据结构。

2.2 其他类型的索引

B-Tree并非适用于所有场景。在某些特定情况下,SQLite还支持其他类型的索引,如:

  1. 全文索引(FTS):全文索引用于全文搜索,可以快速找到包含特定词汇的文本。SQLite使用一种称为虚拟表的特殊结构来实现全文索引。全文索引通常使用倒排索引(Inverted Index)数据结构来实现。

  2. R-Tree索引:R-Tree索引用于空间数据查询,可以快速找到满足特定空间条件的数据。R-Tree索引适用于处理多维数据,如地理位置数据、时间序列数据等。

2.3 小结

总之,SQLite选择B-Tree作为索引的数据结构,主要是因为它在查询效率、插入和删除效率、有序存储和磁盘友好性方面的优势。在特定场景下,SQLite还支持全文索引和R-Tree索引以满足不同的需求。但是索引并非总是有效的。在某些情况下,索引可能失效,例如查询条件使用了函数或表达式,或者查询条件不满足索引的列顺序。

三、事务处理中的一致性问题

脏读、不可重复读和幻读是数据库事务处理中常见的一致性问题。以下是它们的含义和出现场景:

3.1 脏读(Dirty Read)

脏读是指一个事务读取到了另一个事务尚未提交的数据。这可能导致数据不一致,因为读取到的数据可能会在未来被回滚。脏读通常出现在数据库的隔离级别设置为**“读未提交”**(Read Uncommitted)时。

场景:假设有两个并发事务A和B。事务A修改了一条记录,但尚未提交。此时,事务B读取了这条记录。如果事务A最后回滚了修改,那么事务B读取到的数据就是脏数据。

3.2 不可重复读(Non-repeatable Read)

不可重复读是指在同一个事务中,对同一数据的多次读取返回的结果不一致。这通常是因为在两次读取之间,另一个事务修改了该数据并提交。不可重复读主要出现在数据库的隔离级别设置为**“读已提交”**(Read Committed)时。

场景:假设有两个并发事务A和B。事务A首先读取了一条记录。此时,事务B修改了这条记录并提交。接着,事务A再次读取这条记录,发现数据已经发生了变化,导致不可重复读。

3.3 幻读(Phantom Read)

幻读是指在同一个事务中,对同一范围的数据进行查询时,返回的记录数不一致。这通常是因为在两次查询之间,另一个事务插入或删除了符合查询条件的记录并提交。幻读主要出现在数据库的隔离级别设置为**“可重复读”**(Repeatable Read)时。

场景:假设有两个并发事务A和B。事务A查询年龄在20-30岁之间的用户。此时,事务B插入了一条年龄为25岁的用户记录并提交。接着,事务A再次查询年龄在20-30岁之间的用户,发现记录数增加了,导致幻读。

3.4 小结

在这里插入图片描述

  • 在“读未提交”隔离级别下,可能发生脏读、不可重复读和幻读现象;
  • 在“读提交”隔离级别下,可能发生不可重复读和幻读现象,但是不可能发生脏读现象;
  • 在“可重复读”隔离级别下,可能发生幻读现象,但是不可能脏读和不可重复读现象;
  • 在“串行化”隔离级别下,脏读、不可重复读和幻读现象都不可能会发生。

为了解决这些一致性问题,数据库提供了不同的事务隔离级别。较高的隔离级别可以提供更好的一致性保证,但可能导致较低的并发性能。在实际应用中,需要根据数据一致性和并发性能的需求,选择合适的事务隔离级别。

四、事务隔离级别和MVCC实现

SQLite实际上只支持两种事务隔离级别:串行化(SERIALIZABLE)和可重复读(REPEATABLE READ)。然而,由于其底层的多版本并发控制(MVCC)实现,SQLite的可重复读隔离级别在某些情况下表现得类似于读已提交(READ COMMITTED)隔离级别。以下是SQLite事务隔离级别的详细解释。

4.1 串行化(SERIALIZABLE)

串行化是最严格的事务隔离级别。在串行化隔离级别下,事务按顺序一个接一个地执行,即每个事务在其他事务完成之后才能开始执行。这种隔离级别可以防止脏读、不可重复读和幻读等问题,但并发性能较低。

在SQLite中,串行化隔离级别通过在读取数据时获取共享锁(shared lock),在写入数据时获取排他锁(exclusive lock)来实现。在btree.c文件中,当一个事务开始时,SQLite会调用sqlite3BtreeBeginTrans函数获取一个共享锁(SHARED)。共享锁允许多个事务同时读取数据,但阻止其他事务写入数据。排他锁允许一个事务写入数据,但阻止其他事务读取或写入数据

4.2 可重复读(REPEATABLE READ)

可重复读隔离级别允许多个事务并发读取数据,但阻止其他事务在同一事务期间修改数据。这种隔离级别可以防止脏读和不可重复读,但可能导致幻读。

在SQLite中,可重复读隔离级别通过MVCC实现。在pager.c文件中,SQLite使用MVCC来管理多个并发事务。每个事务都有一个唯一的事务ID,用于标识事务的版本。

  • 当事务读取数据时,SQLite会调用pagerAcquire函数获取一个数据页面。这个函数会检查每个页面的版本,只返回事务ID小于或等于当前事务ID的版本。
  • 当事务写入数据时,SQLite会创建一个新的数据页面,并将其事务ID设置为当前事务ID。这样,每个事务都可以看到一个一致的数据快照,而不会被其他事务的更新干扰。

由于SQLite的MVCC实现,可重复读隔离级别在某些情况下表现得类似于读已提交隔离级别。这是因为当一个事务读取数据时,它实际上可以看到其他已提交事务的更新。然而,同一事务内的多次读取仍然是一致的,因为事务只能看到其开始时已经存在的数据版本。

请注意,SQLite不支持读未提交(READ UNCOMMITTED)隔离级别。读未提交隔离级别允许事务读取尚未提交的数据,可能导致脏读、不可重复读和幻读等问题。

4.3 小结

总结一下,SQLite通过MVCC实现了串行化和可重复读两种事务隔离级别。虽然可重复读隔离级别在某些情况下表现得类似于读已提交隔离级别,但它仍然可以提供一致的数据快照,防止脏读和不可重复读。

五、锁的类型和级别

SQLite使用一种基于磁盘文件的锁定机制,支持五种不同的锁定级别:未锁定(UNLOCKED)、共享(SHARED)、保留(RESERVED)、挂起(PENDING)和排他(EXCLUSIVE)。这些级别从低到高,每个级别的锁都可以阻止更高级别的锁,但不能阻止更低级别的锁。例如,共享锁可以阻止其他事务获取排他锁,但不能阻止其他事务获取共享锁。这些锁定级别在SQLite源码的sqlite3.h头文件中定义,具体实现在os_unix.c(Unix系统)和os_win.c(Windows系统)等文件中。

以下是这五种锁定级别的详细解释。

5.1 未锁定(UNLOCKED)

这是数据库的默认状态,表示没有任何事务正在访问数据库。在这种状态下,任何事务都可以获取共享锁或排他锁。

5.2 共享(SHARED)

在这种状态下,一个或多个事务可以同时读取数据库,但不能写入。当一个事务想要读取数据库时,它需要获取一个共享锁。如果当前没有排他锁或挂起锁,那么获取共享锁的请求将被允许。

5.3 保留(RESERVED)

在这种状态下,一个事务已经表示了写入数据库的意图,但还没有实际执行写入操作。只有一个事务可以持有保留锁,但其他事务仍然可以获取共享锁来读取数据库。当一个事务想要写入数据库时,它首先需要升级其共享锁到保留锁。

5.4 挂起(PENDING)

在这种状态下,一个事务正在等待写入数据库,但需要等待所有的共享锁释放。一旦所有的共享锁被释放,该事务将升级其保留锁到排他锁,并开始写入操作。在挂起状态下,不允许新的共享锁,但已经存在的共享锁可以继续存在直到完成。

5.5 排他(EXCLUSIVE)

在这种状态下,一个事务正在写入数据库。只有一个事务可以持有排他锁,而且在这个事务释放排他锁之前,其他事务不能获取共享锁或排他锁。只有在排他状态下,事务才能写入数据库。

5.6 锁定级别的转换关系

这些锁定级别的转换关系如下:

UNLOCKED -> SHARED -> RESERVED -> PENDING -> EXCLUSIVE

事务可以升级其锁定级别,但不能降级。例如,一个事务可以从共享锁升级到保留锁,但不能从保留锁降级到共享锁。当事务完成时,它需要释放其持有的所有锁,将数据库状态恢复到未锁定状态。

这种锁定机制使得SQLite能够支持多个并发读取事务,以及一个写入事务。通过合理地使用和管理这些锁,SQLite能够在保证数据一致性的同时,实现较高的并发性能。

六、总结

总的来说,SQLite是一款功能强大的轻量级数据库。了解SQLite的存储引擎、索引、事务和锁对于使用SQLite开发应用非常重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/503411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python实战之进阶篇(二)

一. python中的继承 二. 多继承 如果一个类继承了多个类, 多个父类中有相同的方法, 相同的方法则按照继承的顺序,继承第一个父类的 如果子类重写父类中继承的方法, 则子类中重写的方法生效 三. 继承与多态

数据结构03:栈、队列和数组 栈习题01[C++]

考研笔记整理~🥝🥝 之前的博文链接在此:数据结构03:栈、队列和数组_-CSDN博客~🥝🥝 本篇作为链表的代码补充,供小伙伴们参考~🥝🥝 第1版:王道书的课后习题…

ubuntu22.04@Jetson Orin Nano安装配置VNC服务端

ubuntu22.04Jetson Orin Nano安装&配置VNC服务端 1. 源由2. 环境3. VNC安装Step 1: update and install xserver-xorg-video-dummyStep 2: Create config for dummy virtual displayStep3: Add the following contents in xorg.conf.dummyStep 4: Update /etc/X11/xorg.con…

使用Flink实现MySQL到Kafka的数据流转换

使用Flink实现MySQL到Kafka的数据流转换 本篇博客将介绍如何使用Flink将数据从MySQL数据库实时传输到Kafka,这是一个常见的用例,适用于需要实时数据connector的场景。 环境准备 在开始之前,确保你的环境中已经安装了以下软件:…

再次加深理解Java中的并发编程

目录 一、线程、进程、程序 二、线程状态 三、线程的七大参数 四、lock与synchronized锁机制 一)、lock与synchronized锁区别 二)、synchronized锁原理 三)、Lock锁原理 五、synchronized锁升级原理 一)、锁升级基础知识 …

超文本传输协议HTTP

HTTP协议 在网络通信中,我们可以自己进行定制协议,但是也有许多已经十分成熟的应用层协议,比如我们下面说的HTTP协议。 HTTP协议简介 HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一…

JAVAEE之网络编程

1.网络编程 网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。 当然,我们只要满足进程不同就行; 所以即便是同一个主机,只要是不同进程&am…

算法学习——LeetCode力扣图论篇1

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣(LeetCode) 描述 给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特…

elementui 导航菜单栏和Breadcrumb 面包屑关联

系列文章目录 一、elementui 导航菜单栏和Breadcrumb 面包屑关联 文章目录 系列文章目录前言一、elementui 导航菜单栏和Breadcrumb 面包屑怎么关联?二、实现效果三、实现步骤1.本项目演示布局2.添加面包屑2.实现breadcrumbName方法3.监听方法4.路由指配5.路由配置…

【C语言】Infiniband驱动mlx4_reset

一、注释 这个 mlx4_reset 函数负责重置 Mellanox 设备。它保存了设备的 PCI 头信息,然后重置了设备,之后还原保存的 PCI 头信息。请注意,该函数是用英文注释的,下面提供中文注释的版本。以下是该函数的流程: 1. 为保…

springboot项目学习-瑞吉外卖(4)续

1.任务 菜品的添加功能(涉及到两张表的数据添加) 2.菜品添加 功能页面如上,该页面有两个注意点 菜品分类:点击菜品分类后,会展示当前已有菜品:这个功能的实现要从category表里查询数据,然后再做展示口味做法配置&#…

SRS OBS利用RTMP协议实现音视频推拉流

参考:https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started 1)docker直接运行SRS服务: docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5运行起来后可以http://localho…

java Web 疫苗预约管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 疫苗预约管理系统是一套完善的web设计系统,对理解JSP java 编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0,使…

kaggle竞赛(房价预测)(Pytorch 06)

一 下载数据集 此数据集由Bart de Cock于2011年收集,涵盖了2006‐2010年期间 亚利桑那州 埃姆斯市的房价。 下载地址: import hashlib import os import tarfile import zipfile import requests#save DATA_HUB dict() DATA_URL http://d2l-data.s3…

“崖山数据库杯”深圳大学程序设计竞赛(正式赛)M题 一图秒

“崖山数据库杯”深圳大学程序设计竞赛(正式赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) —————— 可以去牛客看题解: 题解 | #暂时没想法#_牛客博客 (nowcoder.net) —————— 上面的就是题解了。…

Adobe Illustrator 2023 for Mac/Win:创意无限,设计无界

在数字艺术与设计领域,Adobe Illustrator 2023无疑是一颗璀璨的明星。这款专为Mac和Windows用户打造的矢量图形设计软件,以其强大的功能和卓越的性能,赢得了全球设计师的广泛赞誉。 Adobe Illustrator 2023在继承前代版本优点的基础上&#…

基于ARM内核的智能手环(day1)

整体介绍 智能手环由 ARM 内核 MCU(Cortex-M 系列)、TFTLCD 屏、温湿度传感器、心率传感器、 加速度传感器等主要几部分构成。该平台硬件采用 STM32 芯片,通过对温湿度传感器的驱动编写,获取周围温湿度数据,并在 LCD 屏显示,通过对…

设计模式12--组合模式

定义 案例一 案例二 优缺点

docker配置github仓库ghcr国内镜像加速

文章目录 说明ghcr.io简介配置镜像命令地址命令行方式1panel面板方式方式一:配置镜像加速,命令行拉取方式二:配置镜像仓库,可视化拉取 说明 由于使用的容器需要从github下载镜像,服务器在国外下载速度很慢&#xff0c…

MySQL InnoDB 之 多版本并发控制(MVCC)

多版本并发控制(MVCC,Multi-Version Concurrency Control)是数据库管理系统中用于提供高并发性和在事务处理中实现隔离级别的一种技术。MVCC 允许系统在不完全锁定数据库资源的情况下,处理多个并发事务,从而提高了数据…