zoukankan      html  css  js  c++  java
  • SQLite入门与分析(四)Page Cache之事务处理(1)

    写在前面:从本章开始,将对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

  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/hustcat/p/1398558.html
Copyright © 2011-2022 走看看