SQLite数据库的VDBE虚拟机(翻译自sqlite.org)
本文描述了SQLite 2.8所使用的虚拟机。SQLite 3.0和3.1使用的虚拟机概念上 与此相似,但是许多操作码已变化,算法也有些不同。本文可用作SQLite 3.0所 使用的虚拟机背后思想的大致描述,但不能作为虚拟机如何工作的详细参考。 VDBE在处理流程的中部,涉及到库的各个部分。VDBE是SQLite的核心。 些有用的事情。文章使用教程的风格,从简单到复杂,顺着这种方法,我们将分 析SQLite库的大部分模块。阅读完此教程后,你应该对SQLite是如何工作的有一 个很到的理解,从而可以开始研究实际的源代码了。 $1 预备工作 标是查询或者改变数据库。为了这个目标,VDBE的机器语言特别设计成搜索,读 取和修改数据库。 意整数。P2是一个非负整数。P3是一个指向一数据结构的指针或者一个以null结 尾的字符串或者为空。只有几条VDBE指令用到所有的三个操作数。许多指令仅仅 用一两个操作数。大量的指令没有操作数,而是使用执行栈来获取数据和存储结 果。每条指令的细节描述在另一个文档中。 都会被释放,栈中的每个东西都被弹出。因此不需要担心内存泄漏或未回收的资 源问题。 让我们开始看些代码。 $2 Insert操作 下列方法创建的表: 名字分别为one和two。现在我们插入一条记录到这个表中: 库中创建表。然后改变sqlite的输出格式:使用.explain命令倒出VDBE程序。最 后,输入上面的INSERT语句,并且前面加上EXPLAIN。EXPLAIN关键字使得sqlite 打印出VDBE程序,但并不执行。如下所示: 条指令和最后的2条指令总是这个样子不会变化,因此实际的工作是使用七条指 令来完成的。这儿没有跳转,因此程序从上往下执行。下面我们详细分析每条指 令: 是事务在其上开始的数据库文件索引。索引0表示主数据库文件。当一个事务开 始时需要获得写锁,这时其它进程既不能读也不能写这个数据库文件了。一个事 务开始时也创建了一个回滚日志。必须在数据库要改变之前开始一个事务。 后一次读中获取的。P1是数据库数字。该指令保证数据库模式没有被另一个线程 所改变,这种情况下就得从新读取数据库模式。 数据库1用于临时表。 果P3不是NULL那么,P3所表示的字符串代表同样的整数值。这条指令执行完后, 栈如下所示: examp表的根页面是P2(这儿为3)。读写指针可以是任何一个非负整数。但是 VDBE使用一个数组来保存指针。为节省内存,最好从0开始,然后向上增长。这 里P3是要打开表的名字,其时这个是没有用的,仅仅是为了增加易读性。该指令 弹出栈中的数据库号数来作为参数,这里是0号数据库,它表示主数据库,因此 指令执行后栈为空。 新纪录号被压入堆栈。指令执行后栈中如下所示: String指令把它的P3操作数压入栈顶。其后栈如下所示: 数据库文件用来存储记录的二进制格式,MakeRecord新产生的记录压入栈顶。执 行后栈如下所示: 则创建一个新的数据行,若存在则覆盖它。记录数据是栈顶数据,键是下面的一 项。这条指令使得栈被弹出两次。P2是行改变计数,这个技术不断增加,使用 sqlite_last_insert_rowid()函数可以返回行id。如果P2是0的话行改变计数将 不变,插入操作在这条指令中实际体现。 改生效。知道另一个事务开始,没有别的修改出现。Commit指令删除日志文件, 释放写锁。如果指针还是打开的话,读锁继续保持。 统统关闭。P1是sqlite_exec()返回的结果代码。对一个正常的退出,这个结果 码应该是SQLITE_OK (0)。若有错误出现,它将是其它值。当有错误出现是回用 到操作数P2。Halt 0 0 0出现在VDBE运行的每一个程序的结尾。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |