青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

SQLite虛擬機工作原理

SQLite中的虛擬數據庫引擎
如果你想知道SQLite內部是如何運行的,你需要粗略了解一下VDBE的工作原理,從下圖可以看出,VDBE處于系統運行的中部,所以它似乎與大部分的部件都有關系,即使部分代碼不直接與它交互但還是起到了支持作用的,VDBE確實是SQLite的核心部分。
clip_image001

這部分將要介紹VDBE是如何工作的,特別是VDBE指令是如何在一起配合完成對數據庫的操作的,下面先用一些簡單的例子介紹,然后再解決更加復雜的問題,如果讀完了這篇文章,你就會對SQLite如何工作有了很好的理解了。
前言
VDBE
是用虛擬機語言來操作虛擬機的,每個程序的目的都是要訪問和更新數據庫,那么VDBE要執行的虛擬機語言都是專門為查找、讀取、和修改數據庫而做的。
每個VDBE語言指令都包括一個操作符和三個操作數,分別為P1,P2,P3,P1是一個任意的整數,P2是一個非負整數,P3是一個指向一個數據結構或者是一個字符串,也可能是NULL,只有少數VDBE指令用到所有的操作數,很多只用一兩個而已,還有一大部分根本就不用而是把自己的數據存到執行棧中。
一個VDBE程序從第0條指令開始并執行后面的一連串指令直到遇到錯誤或者執行到一個HALT指令。當一個VDBE完成執行任務后,所有的數據游標都關閉了,所有的內存都釋放,所有的數據都從棧中彈出,所以從來不用擔心內存泄漏和沒有釋放資源的問題。

一、向數據庫中插入數據
我們開始用只有很少指令的VDEB程序來解決一個問題,假設我們已經有一個數據表:
CREATE TABLE examp(one text, two int);
也就是說我們現在已經存在一個叫examp名字的表和兩列分別叫onetwo,現在假設我們一插入下面的數據:INSERT INTO examp VALUES(‘Hello, World!’,99);
現在我們就可以看一下這些指令,我們可以先打開SQLite3命令窗口,并且建立好上面的表,并且插入數據,插入語句這樣寫:
EXPLAIN INSERT INTO examp VALUES('Hello, World!',99);
這時就會有下面的指令表產生:
clip_image002

從上面可以看出,對于一個簡單的插入語句它執行了12條指令,前三條和后2條都是指令執行的開始和結尾,而真正執行的工作都是在中間7條完成的,這里沒有跳轉,程序從上面一直到下面執行,現在一條條的解釋其含義:
0 Transaction 0 0
1 VerifyCookie 0 81
2 Transaction 1 0
指令Transaction是在開始一個事務,事務是如果遇到Commit或者Rollback操作符就結束。P1是指示這個事務所在的數據庫文件的索引,0表示是主數據庫文件,當一個事務開始時,在數據庫文件上要加上寫鎖,當一個事務在運行的時候其它的進程就不能讀或者寫這個文件了,開始一下事務也會產生一個回滾日志,在數據庫文件發生任何修改之前事務必須開始。
指令VerifyCookie是檢查數據模式的版本來確保它與它在上次讀數據庫模式得到的信息是一致的。P1是數據庫編號(0表示主數據庫),這樣是為了確保數據庫模式沒有被其它的線程修改。
第二個Transaction指令是在開始一個事務并且對數據庫1產生一個日志文件,這個數據是用于臨時表的。

3 Integer 0 0
4 OpenWrite 0 3 examp
指令Integer是將一個整型值P10)放到棧中,這里的0表示將要修改的數據庫,如果P3不為NULL,那么它將是用一個字符串類型來表達同樣的整數?,F在棧的狀態為:
(integer) 0

指令OpenWrite是在P10)數據庫中,對表examp表打開一個讀/寫游標,它的根頁面是P2(在這個數據庫文件中是3),游標可以是任意一個非負整數,但是VDBE是在一個數組中分配游標的,這個數組的大小為最大游標數加一,所以為了節省內存,最好就是從0位置開始一直加上去。這里的P3是將要被打開的表名,但是這里并沒有使用它,只是為了更好的讀代碼。這條指令會把數據庫編號0從棧中彈出來,所以現在棧又變成空的了。

5 NewRecno 0 0
指令NewRecno是產生一個新的整數記錄來讓游標P1指向它,這個記錄值現在還不被用作關鍵字,新的記錄被存入棧中,現在棧的狀態如下:
(integer) new record key


6 String 0 0 Hello, World!
指令String是將操作數P3放入棧中,現在棧的狀態為:
(string) "Hello, World!"
(integer) new record key


7 Integer 99 0 99
Integer
指令是將操作數P1放入棧中,現在棧的狀態為:
(integer) 99
(string) "Hello, World!"
(integer) new record key


8 MakeRecord 2 0
MakeRecord
指令是將P12個)棧頂數據彈出棧,并且將它們轉換成二進制類型的數據來存入數據庫方件中,被這條指令處理過的記錄又一次壓入棧中,現在棧的狀態為:
(string) "Hello, World!"
99
(integer) new record key


9 PutIntKey 0 1
指令PutIntKey是從棧彈出兩個數據并且將這兩個數據寫入游標P1所指的表中,這個新的記錄如果已經存在則被覆蓋,如果不存在則新創建。這條記錄的值是棧頂記錄,而主鍵則是棧中第二條記錄(注:也就是在SQLite每個表中的系統主鍵rowid)這條指令會使棧彈出兩次,因為操作數P21,所以行的改變數為1并且rowid會存儲到sqlite_last_insert_rowid()函數的返回值中,如果P20,那么行修改數就不會改變,這條指令就說明插入操作所做的工作。

10 Close 0 0
指令Close是關閉一個先前打開的游標P1,如果P1現在處于關閉狀態則這條指令無操作。

11 Commit 0 0
指令Commit會使所有的改變都存儲到數據庫中,在下一個事務開始之前再不會產生任何的修改,這條指令也會刪除日志文件并且釋放了數據庫鎖,如果游標還是在打開狀態的話,一個讀鎖可以繼續持有。

12 Halt 0 0
指令Halt使得VDBE引擎立即退出,所有打開的游標等都自動關閉,操作數P1sqlite_exec()接口的返回值,對于一個正常的Halt,返回應該是SQLITE_OK (0).,如果是出現錯誤,就可能會得到其它的信息,P2操作數只有出現錯誤時候才會用到,也有一個隱含的Halt指令“Halt 0 0 0”在每個程序的結尾,這是VDBE在準備執行的時候附加上去的。

接著上一節的插入原理,現在來講一下查詢的執行原理: 

二、簡單的查詢
到現在為止,已經知道VDBE是如何將數據寫入數據庫中的了,現在下來看看查詢是如何工作的,下面是我們用到的例子:SELECT * FROM examp;
下面就是對執行這條SQL語句產生的指令:
clip_image003

在看這個問題之前我們還是先看一下SQLite的查詢是如何工作的,這樣我們才知道我們需要完成什么工作,對于查詢結果的每一行,SQLite都會調用一個Callback函數:
int Callback(void *pUserData, int nColumn, char *azData[], char *azColumnName[]);
SQLite
庫會給VDBE提供一個指向回調函數的指針和一個pUserData指針(不管是回調函數指針還是pUserData指針,它都是由API函數sqlite_exec()傳進來的)VDBE的工作就是為nColumn、azData[]、azColumnName[]取值,nColumn就是查詢結果的列數,azColumnName[]數組中的每個字符串就是查詢結果的每一列名,azData[]放的是實際的數據。


0 ColumnName 0 0 one
1 ColumnName 1 0 two
VDBE
的查詢程序的前兩條指令是為azColumn設置值的,ColumnName指令是告訴VDBE應該給azColumnName數組設置什么值的,每次查詢都是以ColumnName指令開始的,對查詢結果的每個列都會有這樣的指令。并且在后來的查詢中對于每一列都會有相應的列指令。

2 Integer 0 0
3 OpenRead 0 3 examp
4 VerifyCookie 0 81
指令23打開一個要訪問的數據庫表的游標,這人工作和在插入數據時候用到的OpenWrite指令是差不多的,除了這回打開是用來讀的而那個是寫的,指令4象在插入的例子中一樣是用來驗證數據庫模式的

5 Rewind 0 10
指令Rewind是初始化一個對要查詢表的循環的迭代器,它把游標定位到表的第一個數據上,這是Column指令和下一條指令所需要的,下一條指令將會用這個游標迭代整個表的,如果這個表是空的則跳轉到P210),如果表不是空的,則就跳到下一條指令,從現在開始就到了循環體部分了。

6 Column 0 0
7 Column 0 1
8 Callback 2 0
上面的指令是整個循環體,它對表中的每一條記錄都是只執行一次,上面67指令都是將P2操作數對應的各自的列的數據放到棧中,在這個例子中,第6條指令是將one列中的數據放到棧中,而第7條指令是將two列中的數據放到棧中,第8條指令是引發對回調函數的執行,這時它的P1操作數將會變成查詢結果的列數,這條指令會將P1條記錄出棧并放到azData[]數組中。

9 Next 0 6
這條指令是在執行一個循環的分叉部分,從第5條指令到現在是構成了整個循環的邏輯結構,這是個應該值得注意的關鍵概念,這個指令是將游標前進指向下一條記錄,如果前進成功,那么立即跳轉到這個循環開始,如果這個前進不成功,則繼續執行下面的結束循環的指令,而不跳回。

10 Close 0 0
11 Halt 0 0
Close
指令是在程序的結尾將指向要查詢表的游標關閉,其實沒必要在這里執行這條指令,因為在程序結束后,VDBE都會把所有的游標自動的關閉,Halt指令是用來關閉VDBE程序的。
注意到查詢記錄時沒有用到TransactionCommit指令,而在插入的時候用到了,因為SELECT是個讀操作,而不會改變數據庫,所以它不需要事務。

 

posted on 2009-06-20 03:16 肥仔 閱讀(818) 評論(0)  編輯 收藏 引用 所屬分類: 數據庫

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美午夜电影在线观看| 亚洲人成精品久久久久| 欧美在线影院| 欧美亚洲免费| 久久久久久久999精品视频| 亚洲作爱视频| 亚洲精品一区在线| 亚洲人成精品久久久久| 欧美xart系列高清| 巨乳诱惑日韩免费av| 欧美成人按摩| 亚洲欧洲一区| 亚洲图片欧洲图片av| 久久精品主播| 国产精品第一页第二页第三页| 国产精品久久久久久久一区探花| 国产精品高精视频免费| 亚洲二区视频在线| 欧美在线观看天堂一区二区三区| 久久久久亚洲综合| 亚洲巨乳在线| 亚洲激情图片小说视频| 亚洲视频axxx| 亚洲福利视频二区| 亚洲欧美伊人| 欧美日本一区二区三区| 国产视频亚洲精品| 一区二区三区久久网| 亚洲看片一区| 国产一区二区丝袜高跟鞋图片| 欧美精品成人| 亚洲精品无人区| 亚洲少妇中出一区| 免费观看在线综合| 欧美成人视屏| 国产精品日韩欧美一区| 亚洲成色www8888| 久久综合久久久久88| 一区二区三区日韩精品视频| 欧美国产专区| 亚洲麻豆av| 亚洲高清不卡一区| 久久人91精品久久久久久不卡| 国产精品家庭影院| 久久人人九九| 猫咪成人在线观看| 在线成人激情视频| 免费欧美日韩国产三级电影| 欧美在线视频a| 国产自产高清不卡| 亚洲精品麻豆| 另类天堂视频在线观看| 亚洲欧美精品在线| 欧美激情一区二区三区四区| 性感少妇一区| 欧美一区三区二区在线观看| 久久久久www| 亚洲欧美福利一区二区| 免费不卡欧美自拍视频| 午夜精品免费在线| 欧美日韩视频在线一区二区| 欧美成人乱码一区二区三区| 国产精品资源| 亚洲午夜精品| 欧美一区二区观看视频| 欧美v日韩v国产v| 久久久久久伊人| 国产精品亚洲激情| 这里是久久伊人| 亚洲视频 欧洲视频| 欧美日本高清| 亚洲免费观看高清在线观看 | 在线亚洲一区| 美日韩丰满少妇在线观看| 亚洲第一偷拍| 国产欧美日韩三级| 欧美日韩直播| 欧美日韩高清一区| 欧美激情中文不卡| 99在线热播精品免费| 亚洲综合国产| 在线观看亚洲视频| 欧美精品免费在线观看| 日韩视频免费| 久久成人综合网| 亚洲美女一区| 国产精品永久免费| 美女999久久久精品视频| 欧美激情精品久久久六区热门| 亚洲中字在线| 亚洲中午字幕| 亚洲国产精品va在线观看黑人| 亚洲精品午夜| 国产一区91| 欧美另类综合| 免费毛片一区二区三区久久久| 91久久久国产精品| 美女精品在线观看| 欧美一级二区| 小黄鸭精品aⅴ导航网站入口| 亚洲黄网站黄| 一区二区视频在线观看| 国产欧美日本一区二区三区| 欧美网站大全在线观看| 欧美国产日本| 欧美成人蜜桃| 欧美破处大片在线视频| 久久精品国产精品亚洲综合| 欧美一激情一区二区三区| 午夜精彩视频在线观看不卡| 欧美大片在线观看| 欧美成人伊人久久综合网| 久久久久久网站| 久久另类ts人妖一区二区| 久久免费国产精品1| 欧美成人高清视频| 亚洲精品国产精品乱码不99| 亚洲国产美女| 夜夜嗨av色一区二区不卡| 亚洲精品乱码久久久久久黑人| 欧美激情成人在线| 久久综合久久综合久久| 欧美国产一区在线| 亚洲精品影视| 欧美一区日韩一区| 免费观看日韩| 国产欧美日本| 亚洲图片欧美一区| 免费国产自线拍一欧美视频| av不卡在线观看| 欧美夫妇交换俱乐部在线观看| 欧美激情精品久久久久久蜜臀| 午夜一区二区三视频在线观看| 欧美日韩1234| 亚洲图片激情小说| 中文国产亚洲喷潮| 国产精品视频男人的天堂| 亚洲视频一区二区| 中文日韩在线| 久久综合电影| 国产麻豆日韩| 曰本成人黄色| 久久久久久一区二区三区| 香蕉乱码成人久久天堂爱免费| 久久中文精品| 精品91久久久久| 欧美亚洲日本国产| 亚洲一区二区毛片| 国产精品欧美日韩| 亚洲国产精品悠悠久久琪琪| 欧美在线亚洲一区| 亚洲图片欧洲图片av| 欧美特黄一级| 亚洲综合第一页| 欧美在线啊v| 在线观看日韩精品| 91久久精品美女高潮| 欧美电影在线| 亚洲毛片在线看| 亚洲精品视频在线看| 欧美色综合网| 久久综合99re88久久爱| 欧美成人精品福利| 亚洲视屏在线播放| 中文日韩电影网站| 国产主播一区| 亚洲美女黄网| 国精品一区二区三区| 欧美高潮视频| 国产精品v欧美精品v日本精品动漫| 亚洲欧美日韩一区二区三区在线观看| 亚洲一区二区三区久久| 亚洲国产精品免费| 亚洲私人影院在线观看| 在线观看不卡av| 日韩视频免费观看高清完整版| 亚洲国产91| 一区福利视频| 亚欧美中日韩视频| 一区二区三区免费观看| 久久人人九九| 欧美中文字幕第一页| 欧美三日本三级三级在线播放| 看片网站欧美日韩| 黄色亚洲在线| 欧美一区二区三区另类| 亚洲性视频网址| 欧美午夜不卡视频| 亚洲精品小视频| 一区二区三区四区国产| 老司机午夜精品| 欧美激情第五页| 亚洲国产乱码最新视频| 欧美成人综合一区| 亚洲成人自拍视频| 亚洲日本电影在线| 欧美伦理视频网站| 亚洲视频播放| 性一交一乱一区二区洋洋av| 国产午夜亚洲精品不卡|