小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

SQLite 中的各種限制

 dxw121 2016-09-06

在這篇文章的環(huán)境里,“限制”意味著不能超過設定的大小或者數(shù)量。我們關(guān)心的是諸如在BLOB或者表中最大字節(jié)數(shù)。

SQLite最初被設計成避免任何限制策略的數(shù)據(jù)庫。當然,運行任意程序的機器都有特定大小內(nèi)存和磁盤空間限制。但是在SQLite,哪些限制沒有被定義。該策略是,如果有足夠內(nèi)存并且可以運行在32位機器上,那么它應該可以工作。

不幸的是,沒有限制策略已經(jīng)暴露出問題了。因為上限沒有定義,它們沒經(jīng)過(極限)測試,當把SQLite推向極限時,漏洞(包括潛在的安全隱患)經(jīng)常出現(xiàn)。鑒于此原因,SQLite的新版本明確定義了限制,并且那些限制作為單元測試的一部分。

本文定義了 SQLite 的限制,如何針對這些限制定制特定的應用程序。默認的限制設置通常是適當?shù)?,幾乎適合于每一個應用。有一些應用程序可能需要在這里或者那里增加一個設置,但是我們估計這非常罕見。更普遍的是,應用程序可能需要重新編譯SQLite以及更低的限制來避免過多的資源利用率,以及在高級SQL語句生成器上幫助阻止攻擊者注入惡意SQL語句時發(fā)生錯誤。

在使用 sqlite3_limit() 接口的 limit categories 上,為該接口定義一些限制,可以在運行時改變每個基礎的連接。應用程序設計的運行時限制多數(shù)據(jù)庫,一些僅供內(nèi)部使用的限制可以影響或控制潛在的敵對外部代理。舉例來說,一個web瀏覽器應用程序可能使用一個內(nèi)部的數(shù)據(jù)庫來追蹤歷史頁面瀏覽量,但是它有一個或很多分離的數(shù)據(jù)庫,它們被創(chuàng)建和控制是通過 javascript 應用,這些應用都是從互聯(lián)網(wǎng)上下載的。那么 sqlite3_limit() 接口是允許通過可信代碼來管理約束內(nèi)置數(shù)據(jù)庫的,同時在數(shù)據(jù)庫創(chuàng)建或控制上有著嚴格的限制,它會拒絕不可信的外部代碼攻擊服務。

1、string或者BLOB的最大長度

SQLite中string或者BLOB的最大字節(jié)數(shù)是由預處理器宏SQLITE_MAX_LENGTH定義的。這個宏的默認值是10億,你可以在編譯時使用像下面這樣的命令行參數(shù)來對這個默認值進行調(diào)整:

-DSQLITE_MAX_LENGTH=123456789

在當前實現(xiàn)中僅支持將string或者BLOB長度上調(diào)到最大231-1 or 2147483647。并且這個時候一些內(nèi)置的函數(shù)例如hex()將會調(diào)用失敗。在安全敏感的應用中最好不要嘗試增加string和BlOB的最大長度。實際上,如果可以的話,你可以將string和BLOB的最大長度在一定范圍內(nèi)降低(幾百方字節(jié))。

在SQLite的INSERT和SELECT處理時,數(shù)據(jù)庫中中的每一行的所有內(nèi)容都被編碼成單個BLOB。所以SQLITE_MAX_LENGTH這個參數(shù)同樣也定義了一行的最大字節(jié)數(shù)。string或者BLOB的最大長度可以在運行時通過sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) 方法調(diào)低。

2、最大列數(shù)

SQLITE_MAX_COLUMN在編譯時用來設置一個上限:默認設置SQLITE_MAX_COLUMN的值是2000。你可以在編譯的時候?qū)⑺{(diào)整到最大32767。另一方面,許多經(jīng)驗豐富的數(shù)據(jù)庫設計者會認為一個設計良好的數(shù)據(jù)庫永遠都不會在表中需要超過100列。

在大多數(shù)應用中的列數(shù)是很小的,大約幾十個而已。在SQLite代碼生成器中使用的算法是O(N2),這個N就是列數(shù)。所以如果你重新定義SQLITE_MAX_COLUMN為一個巨大的數(shù)字,那么在生成SQL的時候使用這個大列數(shù)你就會發(fā)現(xiàn)sqlite3_prepare_v2() 運行的很慢。最大列數(shù)可以在運行時使用sqlite3_limit(db,SQLITE_LIMIT_COLUMN,size) 方法調(diào)低。

·表中的列數(shù)
·索引中的列數(shù)
·視圖中的列數(shù)
·UPDATE語句中SET子句中的項數(shù)
·SELECT語句結(jié)果集中的列數(shù)
·GROUP BY 或者 ORDER BY子句中的項數(shù)
·INSERT語句中的value項數(shù)



 
SQL語句的最大長度

一個SQL語句文本中字節(jié)數(shù)的最大值,受限于 SQLITE_MAX_SQL_LENGTH ,其默認為 1000000。你可以重新對這個限制進行定義,大到 SQLITE_MAX_LENGTH 和 1073741824 兩者中較小的一個值。 

如果一個SQL語句在長度上被限制在1百萬個字節(jié)以內(nèi),那么很明顯你就不能夠以字符串字面量的形式將幾百萬字節(jié)嵌入到 INSERT 語句中。不過你應該是不會那樣做的。這時候針對這些數(shù)據(jù)你可以使用占位參數(shù),像下面這樣先準備好一個簡短的SQL語句:

INSERT INTO tab1 VALUES(?,?,?);

然后使用 sqlite3 的_bind_XXXX() 函數(shù)來將大型的字符串值綁定到這個SQL語句。綁定的使用回避掉了要在字符串中對引號進行轉(zhuǎn)義的必要, 同時降低了遭受SQL注入攻擊的風險。它運行起來也更快,因為大型的字符串不必進行其它方式要進行的多次轉(zhuǎn)換和復制操作。

SQL語句的最大長度可以在運行時使用 sqlite3 的_limit(db,SQLITE_LIMIT_SQL_LENGTH,size) 接口來減小。


 
一次連接操作中最大的表數(shù)量

SQLite 不支持超過64個表的連接操作。此限制源于在查詢優(yōu)化器中,SQLite代碼生成器會使用每個連接表一個位的位圖,這一事實。

SQLite 使用了一種高效的 查詢規(guī)劃器算法 ,因此即使是一個大型地連接操作也能被快速地被 預處理好。 所以沒有任何機制來提高或者降低一次連接操作中表的數(shù)量。


 
表達式樹結(jié)構(gòu)的最大深度

SQLite 會將表達解析成一個數(shù)結(jié)構(gòu)來進行處理。在代碼生成期間,SQLite會以遞歸的形式遍歷這個樹結(jié)構(gòu)。表達式樹結(jié)構(gòu)的深度因此被加上了限制,以此避免用掉太多的棧空間。

SQLITE_MAX_EXPR_DEPTH 參數(shù)決定了表達式樹結(jié)構(gòu)的最大深度。如果其值為 0,就表示不加任何限制。目前的實現(xiàn)所使用的默認值是 1000。

如果 SQLITE_MAX_EXPR_DEPTH 初始是正數(shù),那么表達書樹結(jié)構(gòu)的最大深度可以在運行時使用 sqlite3 的_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size) 接口來降低。換言之,如果已經(jīng)在編譯時對表達式深度做了限制,那么表達式樹結(jié)構(gòu)深度的最大值就可以在運行時被降低。如果If SQLITE_MAX_EXPR_DEPTH 的值在編譯時被設置為 0(即表達式的深度不受限制),那么sqlite3 的_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size) 接口就是一個無效操作。


 
函數(shù)里慘呼是的最大數(shù)量

SQLITE_MAX_FUNCTION_ARG 參數(shù)決定了能夠被傳入到一個SQL函數(shù)的參數(shù)的最大數(shù)量。這一限制的默認值為100。SQLite 應該在函擁有數(shù)以千計的參數(shù)時也能運作。不過,我們對于那些使用過多參數(shù)的人持懷疑態(tài)度,因為他們可能是在嘗試找出使用了SQLite的系統(tǒng)中的安全漏洞,而不是做一些實用的事情, 而因為這個原有,我們已經(jīng)給這個參數(shù)設置了相對而言較低的值。

傳入函數(shù)的參數(shù)數(shù)量有時會被存儲在一個有符號的字符中,因此 SQLITE_MAX_FUNCTION_ARG 有一個限定死的 127 的上限。

一個函數(shù)中的參數(shù)的最大數(shù)量可以在運行時使用 sqlite3 的_limit(db,SQLITE_LIMIT_FUNCTION_ARG,size) 接口來降低。


 一個復合SELECT語句中段落最大數(shù)量

一個復合 SELECT 語句就是那種由操作符 UNION, UNION ALL, EXCEPT, 或者 INTERSECT 連接起來的兩個或者更多個SQL語句。我們將一個復合SELECT中的每一個獨立的SELECT語句稱為一個“段落”。

SQLite中的代碼生成器會使用一種遞歸算法來對復合SELECT語句進行處理。對棧的大小有必要進行一下限制,我們會因為這個緣故對復合SELECT中的段落數(shù)量進行限制。段落的最大數(shù)量限制參數(shù)就是 SQLITE_MAX_COMPOUND_SELECT ,其默認值為 500。我們認為這已經(jīng)是一個比較寬裕的分配方案了,因為在實際使用中很少會遇到一個復合SELECT中段落的數(shù)量超過個位數(shù)。

復合SELECT段落的最大數(shù)量在運行時可以使用 sqlite3 的_limit(db,SQLITE_LIMIT_COMPOUND_SELECT,size) 接口來降低。


 
LIKE 或者 GLOB 模式的最大數(shù)量

在特定的一些極端場景中,SQLite默認的LIKE和GLOB實現(xiàn)中所使用的模式匹配算法會表現(xiàn)出 O(N2) 的性能消耗(這里的N指的是模式中字符的數(shù)量。為了避免遭受來自那些能夠自己指定 LIKE 或者 GLOB 模式的人所進行的拒絕服務攻擊, LIKE 或者 GLOB 模式的長度被 SQLITE_MAX_LIKE_PATTERN_LENGTH 所指定的位數(shù)值進行了限定。這個的默認值為 50000?,F(xiàn)代的工作站能夠以相對較快的速度計算出一個擁有50000位這樣極端長度的 LIKE 或者 GLOB 模式。拒絕服務攻擊的問題只有在模式長度達到百萬個字節(jié)位數(shù)這樣的程度時才會造成影響。不過因為大多數(shù)實用的 LIKE 或者 GLOB模式長度大多只有幾十個字節(jié),偏執(zhí)的開發(fā)者如果知道外部用戶擁有生成任意模式的能力,也許就會想要把這個參數(shù)限制到幾百個這樣的范圍之內(nèi)。 

LIKE 或者 GLOB 模式的最大長度可以在運行時使用 sqlite3 的_limit(db,SQLITE_LIMIT_LIKE_PATTERN_LENGTH,size) 接口來減小。


 
單個SQL語句中預置參數(shù)的最大個數(shù)

預置參數(shù)就是SQL語句中的一個占位符,將來會被使用sqlite3 其中的一個_bind_XXXX() 接口填充。許多SQL程序員對于使用問號 ('?') 作為預置參數(shù)都很熟悉。SQLite 也支持以前置 ':', '$', 或者 '@'的命名作為預置參數(shù),并且以“?123”這樣的形式對預置參數(shù)進行編號。

SQLite語句中的每一個預置參數(shù)都被分配了一個數(shù)字。該數(shù)字一般以1開始,而后對于每一個新的參數(shù)其數(shù)字加一。然而,當“?123”這樣的形式被使用了的時候,預置參數(shù)的編號就會是問號后面跟著的那個數(shù)字。

SQLite 會給從1到最大預置參數(shù)數(shù)量之間的預置參數(shù)分配空間。因此,一個包含了像 ?1000000000 這樣的預置參數(shù)的SQL就會需要千兆字節(jié)的存儲。這樣就會很容易地超過主機的資源供應能力。為了防止這種過度了內(nèi)存分配,預置參數(shù)的最大數(shù)量就要限制到 SQLITE_MAX_VARIABLE_NUMBER 這樣一個固定值,其默認為 999。

預置參數(shù)的最大數(shù)量可以在運行時使用 sqlite3 的_limit(db,SQLITE_LIMIT_VARIABLE_NUMBER,size) 接口來減小。


 
觸發(fā)器遞歸的最大深度

SQLite 限制了觸發(fā)器的遞歸深度,一次來阻止一個涉及到遞歸觸發(fā)器的語句毫無限度的使用內(nèi)存。

版本 3.6.18之前的SQLite,觸發(fā)器并非遞歸的,因此這一限制毫無意義。從版本3.6.18開始,遞歸觸發(fā)器得到了支持,但必須使用 PRAGMA recursive_triggers 語句來明確聲明啟用了它。從版本3.7.0開始,遞歸觸發(fā)器就是默認被啟用了的,但可以使用 PRAGMA recursive_triggers 來手動禁用。SQLITE_MAX_TRIGGER_DEPTH 只在其啟用時有效。

觸發(fā)器遞歸的默認的最大深度為1000。


 
從屬數(shù)據(jù)庫的最大數(shù)量

ATTACH 語句是一項SQLite擴展,它能讓兩個或者更多個數(shù)據(jù)庫與同一個數(shù)據(jù)庫連接聯(lián)合起來,操作起來就好像它們是一個數(shù)據(jù)庫。能夠被聯(lián)合的數(shù)據(jù)庫數(shù)量被限制到了 SQLITE_MAX_ATTACHED 這樣一個常量,其默認值為10。被聯(lián)合數(shù)據(jù)庫的最大數(shù)量不能超過125。

被聯(lián)合的數(shù)據(jù)庫的最大數(shù)量可以在運行時使用 sqlite3_limit(db,SQLITE_LIMIT_ATTACHED,size) 接口來減小。


 
一個數(shù)據(jù)庫文件中頁面的最大數(shù)量

SQLite 能夠限制數(shù)據(jù)庫文件的大小,以阻止數(shù)據(jù)庫文件變得太大而消耗過多的磁盤空間。

SQLITE_MAX_PAGE_COUNT 參數(shù),一般會被設置成 1073741823, 就是一個數(shù)據(jù)庫文件中頁面的最大數(shù)量。一次會造成數(shù)據(jù)庫文件增長超過這個值的插入新數(shù)據(jù)的操作將會返回 SQLITE_FULL。

SQLITE_MAX_PAGE_COUNT 最大的可能設置是 214748364。當最大頁面大小為 65536 時, 最大的SQLite數(shù)據(jù)庫大小就大概是140太字節(jié)。最大頁面總數(shù)PRAGMA 可以被用來在運行時提高或者降低這個限制。


 
表中數(shù)據(jù)行的最大數(shù)量

表中數(shù)據(jù)行的最大數(shù)量理論上可以到 264 (18446744073709551616 or about 1.8e 19)。這一限制是不可及的,因為數(shù)據(jù)庫會首先達到140太字節(jié)的大小限制。一個140太字節(jié)大小的數(shù)據(jù)庫可以容納超過將近 1e 13 行的數(shù)據(jù),而要容納這么多行數(shù)據(jù),只能在沒有指數(shù)數(shù)據(jù)存在,并且每一行只包含非常少量數(shù)據(jù)的時候。


 
最大數(shù)據(jù)庫大小

每個數(shù)據(jù)庫都包含一個或多個“頁”(page)。在某個單一數(shù)據(jù)庫中,每個頁的大小相同,但是不同的數(shù)據(jù)庫擁有不同的頁大小,大小介于512字節(jié)(含)和65536字節(jié)(含)之間。一個數(shù)據(jù)庫文件最多包括2147483646頁。每個頁最大65536字節(jié),換算可得最大數(shù)據(jù)庫大小約為1.4e 14字節(jié)(140千萬兆字節(jié)或128太字節(jié)或140000百萬兆字節(jié)或128000吉字節(jié))。

由于開發(fā)人員沒有能滿足這個限制的硬件條件,所以沒有對這個上限進行測試。然而,測試表明當數(shù)據(jù)庫達到底層文件系統(tǒng)的最大文件大?。ㄍǔR壤碚撋系淖畲髷?shù)據(jù)庫大小小很多)并且由于磁盤空間耗盡而無法擴展時,SQLite依然能正確并穩(wěn)健地運行。


 
模式中表的最大數(shù)量

數(shù)據(jù)庫文件中的每個表和索引至少需要一個頁。這里的索引可以使用CREATE INDEX 語句顯式地創(chuàng)建,也可以通過UNIQUE和PRIMARY KEY約束隱式地創(chuàng)建。由于數(shù)據(jù)庫文件的頁的最大數(shù)量是2147483646(比20億還多),所以模式中表和索引的數(shù)量上限也是這個。

只要數(shù)據(jù)庫被打開,就會掃描和解析整個模式,并將模式的解析樹存儲在內(nèi)存中。也就是說數(shù)據(jù)庫的啟動時間和初始內(nèi)存使用率與模式大小成正比。


    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多