写在前面:从本章开始,将对SQLite的每个模块进行讨论。讨论的顺序按照我阅读SQLite的顺序来进行,由于项目的需要,以及时间关系,不能给出一个完整的计划,但是我会先讨论我认为比较重要的内容。本节讨论SQLite的事务处理技术,事务处理是DBMS中最关键的技术,对SQLite也一样,它涉及到并发控制,以及故障恢复,由于内容较多,分为两节。好了,下面进入正题。

本节通过一个具体的例子来分析SQLite原子提交的实现(基于Version 3.3.6的代码)。
CREATE TABLE episodes( id integer primary key,name text, cid int) ;
插入一条记录:insert into episodes(name,cid) values("cat",1) ;
它经过编译器处理后生成的虚拟机代码如下:
sqlite> explain insert into episodes(name,cid) values("cat",1);
0|Trace|0|0|0|explain insert into episodes(name,cid) values("cat",1);|00|
1|Goto|0|12|0||00|
2|SetNumColumns|0|3|0||00|
3|OpenWrite|0|2|0||00|
4|NewRowid|0|2|0||00|
5|Null|0|3|0||00|
6|String8|0|4|0|cat|00|
7|Integer|1|5|0||00|
8|MakeRecord|3|3|6|dad|00|
9|Insert|0|6|2|episodes|0b|
10|Close|0|0|0||00|
11|Halt|0|0|0||00|
12|Transaction|0|1|0||00|
13|VerifyCookie|0|1|0||00|
14|Transaction|1|1|0||00|
15|VerifyCookie|1|0|0||00|

16|TableLock|0|2|1|episodes|00|

17|Goto|0|2|0||00|

1、初始状态(Initial State)
当一个数据库连接第一次打开时,状态如图所示。图中最右边(“Disk”标注)表示保存在存储设备中的内容。每个方框代表一个扇区。蓝色的块表示这个扇区保存了原始数据。图中中间区域是操作系统的磁盘缓冲区。开始的时候,这些缓存是还没有被使用,因此这些方框是空白的。图中左边区域显示SQLite用户进程的内存。因为这个数据库连接刚刚打开,所以还没有任何数据记录被读入,所以这些内存也是空的。

2、获取读锁(Acquiring A Read Lock)
在SQLite写数据库之前,它必须先从数据库中读取相关信息。比如,在插入新的数据时,SQLite会先从sqlite_master表中读取数据库模式(相当于数据字典),以便编译器对INSERT语句进行分析,确定数据插入的位置。
在进行读操作之前,必须先获取数据库的共享锁(shared lock),共享锁允许两个或更多的连接在同一时刻读取数据库。但是共享锁不允许其它连接对数据库进行写操作。
shared lock存在于操作系统磁盘缓存,而不是磁盘本身。文件锁的本质只是操作系统的内核数据结构,当操作系统崩溃或掉电时,这些内核数据也会随之消失。

3、读取数据
一旦得到shared lock,就可以进行读操作。如图所示,数据先由OS从磁盘读取到OS缓存,然后再由OS移到用户进程空间。一般来说,数据库文件分为很多页,而一次读操作只读取一小部分页面。如图,从8个页面读取3个页面。

4、获取Reserved Lock
在对数据进行修改操作之前,先要获取数据库文件的Reserved Lock,Reserved Lock和shared lock的相似之处在于,它们都允许其它进程对数据库文件进行读操作。Reserved Lock和Shared Lock可以共存,但是只能是一个Reserved Lock和多个Shared Lock——多个Reserved Lock不能共存。所以,在同一时刻,只能进行一个写操作。
Reserved Lock意味着当前进程(连接)想修改数据库文件,但是还没开始修改操作,所以其它的进程可以读数据库,但不能写数据库。

5、创建恢复日志(Creating A Rollback Journal File)
在对数据库进行写操作之前,SQLite先要创建一个单独的日志文件,然后把要修改的页面的原始数据写入日志。回滚日志包含一个日志头(图中的绿色)——记录数据库文件的原始大小。所以即使数据库文件大小改变了,我们仍知道数据库的原始大小。
从OS的角度来看,当一个文件创建时,大多数OS(Windows,Linux,Mac OS X)不会向磁盘写入数据,新创建的文件此时位于磁盘缓存中,之后才会真正写入磁盘。如图,日志文件位于OS磁盘缓存中,而不是位于磁盘。

上面 5步的代码的实现:

Code

其实现过程如下图所示:

主要参考:http://www.sqlite.org/atomiccommit.html

SQLite入门与分析(四)---Page Cache之事务处理(1)的更多相关文章

  1. SQLite入门与分析(四)---Page Cache之事务处理(3)

    写在前面:由于内容较多,所以断续没有写完的内容. 11.删除日志文件(Deleting The Rollback Journal)一旦更改写入设备,日志文件将会被删除,这是事务真正提交的时刻.如果在这 ...

  2. SQLite入门与分析(四)---Page Cache之事务处理(2)

    写在前面:个人认为pager层是SQLite实现最为核心的模块,它具有四大功能:I/O,页面缓存,并发控制和日志恢复.而这些功能不仅是上层Btree的基础,而且对系统的性能和健壮性有关至关重要的影响. ...

  3. SQLite入门与分析(五)---Page Cache之并发控制

    写在前面:本节主要谈谈SQLite的锁机制,SQLite是基于锁来实现并发控制的,所以本节的内容实际上是属于事务处理的,但是SQLite的锁机制实现非常的简单而巧妙,所以在这里单独讨论一下.如果真正理 ...

  4. SQLite入门与分析(二)---设计与概念(续)

    SQLite入门与分析(二)---设计与概念(续)   写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...

  5. SQLite 入门教程(四)增删改查,有讲究 (转)

    转于: SQLite 入门教程(四)增删改查,有讲究 一.插入数据 INSERT INTO 表(列...) VALUES(值...) 根据前面几篇的内容,我们可以很轻送的创建一个数据表,并向其中插入一 ...

  6. SQLite入门与分析(三)---内核概述(2)

    写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...

  7. SQLite入门与分析(二)---设计与概念

    写在前面:谢谢各位的关注,没想到会有这么多人关注.高兴的同时,也感到压力,因为我接触SQLite也就几天,也没在实际开发中用过,只是最近项目的需求才来研究它,所以我很担心自己的文章是否会有错误,误导别 ...

  8. SQLite入门与分析(八)---存储模型(1)

    写在前面:SQLite作为嵌入式数据库,通常针对的应用的数据量相对于通常DBMS的数据量是较小的.所以它的存储模型设计得非常简单,总的来说,SQLite把一个数据文件分成若干大小相等的页面,然后以B树 ...

  9. SQLite入门与分析(一)---简介

    写在前面:出于项目的需要,最近打算对SQLite的内核进行一个完整的剖析,在此希望和对SQLite有兴趣的一起交流.我知道,这是一个漫长的过程,就像曾经去读Linux内核一样,这个过程也将是辛苦的,但 ...

随机推荐

  1. 通过命令行连接oracle数据库/进入sql plus

    1.直接打开SQL Plus登录,需要用户名和密码 开始->程序->Oracle->应用程序开发->sqlplus 我的电脑是“开始”->“Oracle - OraDb1 ...

  2. jQuery动态添加元素并绑定事件

    写网页的时候常常需要根据实际情况添加新的元素,然后这些新元素还需要绑定已有的事件,如:有一ul,点击其中某 li,根据其 id 或 value 等获取新的数据列表,并新建 ul 显示,新 ul 中的 ...

  3. C/C++编译过程理解【转】

    转载自:http://www.cppblog.com/woaidongmao/archive/2008/11/07/66254.aspx 今天,通过自己的努力终于对C/C++的编译过程有了个粗略的了解 ...

  4. 第三章 用SDK编译出第一个在Linux下的软件界面

    第三章 用SDK编译出第一个在Linux下的软件界面 先创建一个工程目录“mkdir project1”,进入目录,创建main.cpp文件,编写代码如下: 代码内容暂时可以先不理解,先让程序跑起来再 ...

  5. 在ThinkPHP3.x框架中实现将原创文章第一时间推送到百度收录

    前两天自己写的一篇文章“针对BootStrap中tabs控件的美化和完善”被别的网站给转载了,这也许是值得高兴的一件事情,但是有些网站并没有注明来源和作者.而去百度搜索这篇文章,排名第一的居然是那些转 ...

  6. php安全设定

    nginx: 在配置文件nginx.conf的http段里加入  server_tokens off;  HTTPD.CONFTraceEnable Off <Directory ~ " ...

  7. wampsever在win10中安装扩展掉坑

    1.必须要退出wampserver 2.php pecl + 3.wampserver 64 3.0.6

  8. Delphi2010中DataSnap技术网摘

    一.为DataSnap系统服务程序添加描述 这几天一直在研究Delphi 2010的DataSnap,感觉功能真是很强大,现在足有理由证明Delphi7该下岗了. DataSnap有三种服务模式,其中 ...

  9. hibernate的n+1问题

    下面选自<精通Hibernate:Java对象持久化技术详解>作者:孙卫琴 在Session的缓存中存放的是相互关联的对象图.默认情况下,当Hibernate从数据库中加载Customer ...

  10. Spark Streaming揭秘 Day27 Job产生机制

    Spark Streaming揭秘 Day27 Job产生机制 今天主要讨论一个问题,就是除了DStream action以外,还有什么地方可以产生Job,这会有助于了解Spark Streaming ...