- 浏览: 29523 次
- 性别:
- 来自: 广州
最新评论
写在前面:从本 章开始,我们开始进入SQLite的内核。为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要。SQLite的 内核实现不是很难,但是也不是很简单。总的来说分为三个部分,本章主要讨论虚拟机(Virtual Machine),但是这里只是从原理上概述,不会太多的涉及实际代码。但是概述完内核之后会仔细讨论源代码的。好了,下面我们来讨论虚拟机(VM)。
1、虚拟机(Virtual Machine)
VDBE是
SQLite的核心,它的上层模块和下层模块都是本质上都是为它服务的。它的实现位于vbde.c, vdbe.h, vdbeapi.c,
vdbeInt.h,
和vdbemem.c几个文件中。它通过底层的基础设施B+Tree执行由编译器(Compiler)生成的字节代码,这种字节代码程序语言
(bytecode programming lauguage)是为了进行查询,读取和修改数据库而专门设计的。
字节代码在内存中被封装成
sqlite3_stmt对象(内部叫做Vdbe,见vdbeInt.h),Vdbe(或者说statement)包含执行程序所需要的一切:
a) a bytecode program
b)
names and data types for all result columns
c) values bound to
input parameters
d) a program counter
e) an execution stack
of operands
f) an arbitrary amount of "numbered" memory cells
g)
other run-time state information (such as open BTree objects, sorters,
lists, sets)
字节代码和汇编程序十分类似,每一条指令由操作码和三个操作数构
成:<opcode, P1, P2,
P3>。Opcode为一定功能的操作码,为了理解,可以看成一个函数。P1是32位的有符号整数,p2是31位的无符号整数,它通常是导致跳转
(jump)的指令的目标地址(destination),当然这了有其它用途;p3为一个以null结尾的字符串或者其它结构体的指针。和C
API不同的是,VDBE操作码经常变化,所以不应该用字节码写程序。
下面的几个C API直接和VDBE交互:
• sqlite3_bind_xxx() functions • sqlite3_step() • sqlite3_reset() • sqlite3_column_xxx() functions • sqlite3_finalize()
为了有个感性,下面
看一个具体的字节码程序:
sqlite> .m col sqlite> .h on sqlite> .w 4 15 3 3 15 sqlite> explain select * from episodes; addr opcode p1 p2 p3 ---- --------------- --- --- --------------- 0 Goto 0 12 1 Integer 0 0 2 OpenRead 0 2 # episodes 3 SetNumColumns 0 3 4 Rewind 0 10 5 Recno 0 0 6 Column 0 1 7 Column 0 2 8 Callback 3 0 9 Next 0 5 10 Close 0 0 11 Halt 0 0 12 Transaction 0 0 13 VerifyCookie 0 10 14 Goto 0 1 15 Noop 0 0
1.1、 栈(Stack)
一个
VDBE程序通常由不同完成特定任务的段(section)构成,每一个段中,都有一些操作栈的指令。这是由于不同的指令有不同个数的参数,一些指令只有
一个参数;一些指令没有参数;一些指令有好几个参数,这种情况下,三个操作数就不能满足。
考虑到这些情况,指令采用栈来传递参数。(注:从汇编的
角度来看,传递参数的方式有好几种,比如:寄存器,全局变量,而堆栈是现代语言常用的方式,它具有很大的灵活性)。而这些指令不会自己做这些事情,所以在
它们之前,需要其它一些指令的帮助。VDBE把计算的中间结果保存到内存单元(memory
cells)中,其实,堆栈和内存单元都是基于Mem(见vdbeInt.h)数据结构(注:这里的栈,内存单元都是虚拟的,记得一位计算机科学家说过:计算机科学中90%以上的科学都是虚拟化问题。一点不假,OS本质上也是
虚拟机,而在这里SQLite,我们也处处可见虚拟化的身影,到后面的OS Interface模块中再仔细讨论这个问题
)。
1.2、程序体(Program Body)
这是一个打开
episodes表的过程。
第一条指令:Integer是为第二条指令作准备的,也就是把第二条指令执行需要的参数压入堆栈,OpenRead从
堆栈中取出参数值然后执行。
SQLite可以通过ATTACH命令在一个连接中打开多个数据库文件,每当SQLite打开一个数据,它就为之赋一个索引号(index),main
database的索引为0,第一个数据库为1,依次如此。Integer指令数据库索引的值压入栈,而OpenRead从中取出值,并决定打开哪个数
据,来看看SQLite文档中的解释:
Open a read-only cursor for the database
table whose root page is P2 in a
database file
.
The database file is determined by an integer
from the top of the stack. 0 means the main database and 1 means the
database used for temporary tables. Give
the new cursor an identifier of P1
. The P1 values need not be
contiguous but all P1 values should be small integers. It is an error
for P1 to be negative.
If
P2==0 then take the root page number from off of the stack.
There will be a read lock on the database whenever there is an open
cursor. If the data-
base was unlocked prior to this instruction then
a read lock is acquired as part of this instruction. A read lock allows
other processes to read the database but prohibits any other process
from modifying the database. The read lock is released when all cursors
are closed. If this instruction attempts to get a read lock but fails,
the script terminates with an SQLITE_BUSY error code.
The P3 value is a pointer to a KeyInfo
structure
that defines the content and collating
sequence of indices. P3 is NULL for cursors that are not pointing to
indices.
再来看看SetNumColumns指令设置游标将指向的列。P1为游标的索引(这里为0,刚刚打开),P2为列的数目,episodes表有三
列。
继续Rewind指令,它将游标重新设置到表的开始,它会检查表是否为空(即没有记录),如果没有记录,它会导致指令指针跳到P2指定的指令
处。在这里,P2为10,即Close指令。一旦Rewind设置游标,接下就执行5-9这几条指令,它们的主要功能是遍历结果集,Recno把由游标
P1指定的记录的关键字压入堆栈。Column指令从由P1指定的游标,P2指定的列取值。5,6,7三条指令分别把id(primary
key),season和name字段的值压入栈。接下来,Callback指令从栈中取出三个值(P1),然后形成一个记录数组,存储在内存单元中
(memory cell)。Callback会停止VDBE的操作,把控制权交给sqlite3_stemp(),该函数返回SQLITE_ROW。
一旦VDBE创建了记录结构,我们就可以通过sqlite3_column_xxx()
functions从记录结构的域内取出值。当下次调用sqlite3_step()时,指令指针会指向Next指令,而Next指令会把游标向移向下一
行,如果有其它的记录,它会跳到由P2指定的指令,在这里为指令5,创建一个新的记录结构,一直循环,直到结果集的最后。Close指令会关闭游标,然后
执行Halt指令,结束VDBE程序。
1.3、程序开始与
停止
现在来看看其余的指令,Goto指令是一条跳转指令,跳到P2处,即第12条指令。指令12是Transaction,它开始
一个新的事务;然后执行
VerifyCookie,它的主要功能VDBE程序编译后,数据库模式是否改变(即是否进行过更新操作)。这在SQLite中是一个很重要的概念,在
SQL被sqlite3_prepare()编译成VDBE代码至程序调用sqlite3_step()执行字节码的这段时间,另一个SQL命令可能会改
变数据库模式(such as ALTER TABLE, DROP TABLE, or CREATE
TABLE)。一旦发生这种情况,之前编译的statement就会变得无效,数据库模式信息记录在数据库文件的根页面中。类似,每一个
statement都有一份用来比较的在编译时刻该模式的备份,VerifyCookie的功能就是检查它们是否匹配,如果不匹配,将采取相关操作。
如果两者匹配,会执行下一条指令Goto;它会跳到程序的主要部分,即第一
条指令,打开表读取记录。这里有两点值得注意:
(1)Transaction指令自己不会获取锁( The Transaction
instruction doesn’t acquire any locks in
itself)。它的功能相当于BEGIN,而实际是由OpenRead指令获取share
lock的。当事务关闭时释放锁,这取决于Halt指令,它会进行扫尾工作。
(2)statement对象(VDBE程序)所需的存储空间在程序
执行前就已经确定。这有原于两个重要事实:首先,栈的深度不会比指令的数目还多(通常少得多)。其次,在执行VDBE程序之前,SQLite可以计算出为
分配资源所需要的内存。
1.4指令的类型
(Instruction Types)
每条指令都完成特定的任务,而且通常和别的指令有关。大体上来说,指令可分为三类:
(1)Value
manipulation:这些指令通常完成算术运算,比如:add, subtract,
divide;逻辑运算,比如:AND和OR;还有字符串操作。
(2)Data
management:这些指令操作在内存和磁盘上的数据。内存指令进行栈操作或者在内存单元之间传递数据。磁盘操作指令控制B-tree和pager打
开或操作游标,开始或结束事务,等等。
(3)Control flow:控制指令主要是移动指令指针。
1.5、程序的执行(Program execution)
最
后我们来看VM解释器是如何实现以及字节代码大致是如何执行的。在vdbe.c文件中有一个很关键的函数:
//执行VDBE程序 int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ) 该函数是执行VDBE程序的入口。来看看它的内部实现: /*从这里开始执行指令 **pc为程序计数器(int) */ for(pc=p->pc; rc==SQLITE_OK; pc++){ //取得操作码 pOp = &p->aOp[pc]; switch( pOp->opcode ){ case OP_Goto: { /* jump */ CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; break; } … … } }
从这段代码,我们大致可以推出VM执行的原理:VM解释器实际上是一个包含大量
switch语句的for循环,每一个switch语句实现一个特定的操作指令。
发表评论
-
(转)Andriod是什么
2010-12-02 11:24 1611导读:Sans Serif是Google的 ... -
(转)SQLite入门与分析(六)---再谈SQLite的锁
2010-11-19 00:09 941写在前 面:SQLite封锁机制的实现需要底层文件系统的 ... -
(转)SQLite入门与分析(五)---Page Cache之并发控制
2010-11-19 00:05 1045写在前面:本节主要谈 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(3)
2010-11-19 00:01 950Code 写在前面:由于 内容较多,所以断续没有写完的 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(2)
2010-11-18 23:57 1140写在前面:个人认为pager层是SQLite实现最为核心的 ... -
(转)SQLite入门与分析(四)---Page Cache之事务处理(1)
2010-11-18 23:53 938写在前面:从本章开始,将对SQLite的每个模块进行讨论。 ... -
(转)SQLite入门与分析(三)---内核概述(2)
2010-11-18 23:48 1300写在前面:本节 是前 ... -
(转)SQLite入门与分析(二)---设计与概念(续)
2010-11-18 23:38 1039写在前面:本节 讨论事务,事务是DBMS最核心的技术之一 ... -
(转)SQLite入门与分析(二)---设计与概念
2010-11-18 23:35 789写在前面:谢谢各位的 ... -
(转)SQLite入门与分析(一)
2010-11-18 23:31 904写在前面:出于项目的 需要,最近打算对SQLite的内核 ... -
(转)深入研究B树索引(五)续
2010-11-18 15:10 9245.3 重建 B 树索引 ... -
(转)深入研究B树索引(五)
2010-11-18 15:07 11905. 重建 B ... -
(转)深入研究B树索引(四)续
2010-11-18 14:58 9114.2 B 树索引的对于删除( DEL ... -
(转)深入研究B树索引(三、四)
2010-11-18 14:44 7113. B 树索 ... -
(转)深入研究B树索引(二)
2010-11-18 14:20 7562. B 树索引的内部结构 ... -
(转)深入研究B树索引(一)
2010-11-18 14:12 1000摘要: 本文对B 树索引的结构、内部管理等方面做了一个全面 ... -
(转)B树、B-树、B+树、B*树都是什么
2010-11-17 23:46 671B 树 即二叉搜 ... -
画UML图时注意的几个原则(转)
2010-08-03 12:34 1622软件开发中,分析和设计时,文档的编写和思想的交流,经常要绘制各 ... -
你是个软件架构师吗?(转)
2010-07-14 11:11 661开发和架构的界限难以 ... -
(转)同曲异奏——高效能项目团队的五大特点
2010-03-29 00:24 856同曲异奏——高效能项 ...
相关推荐
1. **SQLite 介绍**: - 数据库引擎:SQLite 是一个事务型数据库引擎,能够处理多种数据类型,支持 ACID(原子性、一致性、隔离性、持久性)事务。 - 文件格式:SQLite 将数据库存储为单个文件,方便在不同系统间...
第1章“SQLite介绍”通常会概述SQLite的特点、历史、适用场景,以及与其他数据库系统的对比。 第2章“入门”会引导读者了解如何安装SQLite,创建数据库,以及进行基本的数据库操作,包括数据的插入、查询、更新和...
在第1章中,通常会介绍Android平台的基本概述,包括它的历史、发展、应用领域以及为什么选择Android作为开发平台。这一章会讲解Android系统架构,包括Linux内核、应用程序框架、应用程序层等组成部分。还会深入到...
1. **Android系统概述** - Android是Google公司主导开发的开源移动操作系统,主要应用于智能手机和平板电脑,但同时也广泛应用于智能电视、车载娱乐系统等。 - Android系统基于Linux内核,拥有丰富的API库和灵活的...
- **定义与历史**: Android是由Google公司开发的基于Linux内核的操作系统,最初由Andy Rubin创立,旨在为手机提供一个开放且完整的服务平台。 - **架构层次**: - **应用程序层**: 包括预装的应用程序如电话簿、...
- **第三代通信技术(3G)**:融合无线通信与互联网多媒体通信,提供更高速的数据传输。 - **第四代通信技术(4G)**:进一步提高了数据传输速度,包括TD-LTE和FDD-LTE两种主要模式。 - **第五代通信技术(5G)**:...
1. **Android系统概述** - **定义与历史**:介绍Android操作系统的基本概念和发展历程。 - **架构层次**:详细介绍Android系统的架构,包括应用程序层、应用程序框架层、核心类库、Linux内核等各个层次的功能和...
根据提供的信息,“Google Android开发入门与实战”这本书是面向初学者到中级水平的程序员的一本指南,内容覆盖了Android开发的基础知识以及实际操作技巧。尽管给出的部分内容并未提供具体章节或知识点,但我们可以...
### Android编程入门(Beginning Android, 5th edition) #### 知识点概览 本章节主要介绍了关于Android编程的基础知识,特别针对初次接触Android开发的学习者。内容涵盖了Android平台的基本介绍、开发环境的搭建...
### Android开发入门经典知识点概述 #### 一、Android的基础概念 - **定义**: Android是一种基于Linux内核的开源操作系统,主要用于移动设备。 - **特点**: - 开源性:任何人都可以自由使用并修改其源代码。 - ...
### Android系统开发入门知识点 #### 一、Android操作系统概述 **Android** 是一款由Google公司开发的基于Linux平台的开放源代码操作系统,主要用于各种移动设备。Android系统包含了操作系统、中间件以及应用程序...
### Google Android 开发入门指南(第二版)知识点总结 #### 一、书籍基本信息与作者介绍 - **书名**:《Google Android 开发入门指南》第二版 - **作者**:Mark L. Murphy 编著;王世江 改编 - **出版时间**:2009...
根据提供的标题“Android开发应用从入门到精通.pdf”和描述“pdf的资源清晰度还不错,有些存在排版有问题,请谨慎下载”,我们可以推断出这份PDF文档涵盖了从基础到高级的Android应用程序开发技术。下面将围绕...
### Android开发入门与实战 #### 一、Android操作系统概述 Android是一种基于Linux内核的开源移动设备操作系统,由Google公司主导开发。自2007年发布以来,Android已经成为全球最大的移动操作系统之一,广泛应用于...
- **定义与历史**:Android是一种基于Linux内核的开源移动操作系统,由Google公司及其领导的开放手机联盟(Open Handset Alliance)共同开发。 - **特点**:Android平台以其高度的可定制性、开放性和广泛的设备支持...