????????MySQL被設(shè)計為一個可移植的數(shù)據(jù)庫, 幾乎在當(dāng)前所有系統(tǒng)上都能運行魂角, 如 Linux, Solaris杠袱、FreeBSD尚猿、Mac和Windows。 盡管各平臺在底層(如線程) 實現(xiàn)方面都各有不同楣富, 但是MySQL基本上能保證在各平臺上的物理體系結(jié)構(gòu)的一致性凿掂。 因此, 用戶應(yīng)該能很好地理解MySQL數(shù)據(jù)庫在所有這些平臺上是如何運作的。
1.1 定義數(shù)據(jù)庫和實例
????????在數(shù)據(jù)庫領(lǐng)域中有兩個詞很容易混淆庄萎, 這就是 “數(shù)據(jù)庫"(database) 和 “ 實例 ” (instance)踪少。 作為常見的數(shù)據(jù)庫術(shù)語, 這兩個詞的定義如下糠涛。
? ??????數(shù)據(jù)庫:物理操作系統(tǒng)文件或其他形式文件類型的集合援奢。 在MySQL數(shù)據(jù)庫中, 數(shù)據(jù)庫文件可以是frm忍捡、MYD集漾、MYI、ibd結(jié)尾的文件锉罐。 當(dāng)使用NDB引擎時帆竹, 數(shù)據(jù)庫的文件可能不是操作系統(tǒng)上的文件, 而是存放于內(nèi)存之中的文件脓规, 但是定義仍然不變栽连。
? ??????實例: MySQL數(shù)據(jù)庫由后臺線程以及一個共享內(nèi)存區(qū)組成。 共享內(nèi)存可以被運行的后臺線程所共享侨舆。 需要牢記的是秒紧, 數(shù)據(jù)庫實例才是真正用于操作數(shù)據(jù)庫文件的。
? ??????在MySQL數(shù)據(jù)庫中挨下, 實例與數(shù)據(jù)庫的關(guān)通常系是一一對應(yīng)的熔恢, 即一個實例對應(yīng)一個數(shù)據(jù)庫, 一個數(shù)據(jù)庫對應(yīng)一 個實例臭笆。 但是叙淌, 在集群情況下可能存在一個數(shù)據(jù)庫被多個數(shù)據(jù)實例使用的情況。
? ??????MySQL被設(shè)計為一個單進程多線程架構(gòu)的數(shù)據(jù)庫愁铺, 這點與SQLServer比較類似鹰霍,但與Oracle多進程的架構(gòu)有所不同(Oracle的Windows版本也是單進程多線程架構(gòu)的)。 這也就是說茵乱, MySQL數(shù)據(jù)庫實例在系統(tǒng)上的表現(xiàn)就是一個進程茂洒。
1.2 MySQL 體系結(jié)構(gòu)
????????從概念上來說,數(shù)據(jù)庫是文件的集合瓶竭,是依照某種數(shù)據(jù)模型組織起來并存放于二級存儲器中的數(shù)據(jù)集合;數(shù)據(jù)庫實例是程序斤贰,是位于用戶與操作系統(tǒng)之間的一層數(shù)據(jù)管理軟件智哀,用戶對數(shù)據(jù)庫數(shù)據(jù)的任何操作,包括數(shù)據(jù)庫定義荧恍、數(shù)據(jù)查詢瓷叫、數(shù)據(jù)維護、數(shù)據(jù)庫運行控制等都是在數(shù)據(jù)庫實例下進行的,應(yīng)用程 序只有通過數(shù)據(jù)庫實例才能和數(shù)據(jù)庫打交道赞辩。
????????從圖 1-1 還可以發(fā)現(xiàn),MySQL數(shù)據(jù)庫區(qū)別于其他數(shù)據(jù)庫的最重要的一個特點就是其插件式的表存儲引擎授艰。MySQL插件式的存儲引擎架構(gòu)提供了一系列標(biāo)準(zhǔn)的管理和服務(wù)支持辨嗽,這些標(biāo)準(zhǔn)與存儲引擎本身無關(guān),可能是每個數(shù)據(jù)庫系統(tǒng)本身都必需的淮腾,如 SQL分析器和優(yōu)化器等糟需,而存儲引擎是底層物理結(jié)構(gòu)的實現(xiàn), 每個存儲引擎開發(fā)者可以按照自己的意愿來進行開發(fā)谷朝。
????????需要特別注意的是洲押,存儲引擎是基于表的,而不是數(shù)據(jù)庫圆凰。此外杈帐,要牢記圖 1-1 的 MySQL體系結(jié)構(gòu),它對于以后深入理解MySQL數(shù)據(jù)庫會有極大的幫助专钉。
1.3 MySQL存儲引擎
? ??????通過1.2節(jié)大致了解了MySQL數(shù)據(jù)庫獨有的插件式體系結(jié)構(gòu)挑童,并了解到存儲引擎是MySQL區(qū)別于其他數(shù)據(jù)庫的一個最重要特性。存儲引擎的好處是跃须,每個存儲引擎都有各自的特點站叼, 能夠根據(jù)具體的應(yīng)用建立不同存儲引擎表。
1.3.1 lnnoDB 存儲引擎
? ??????InnoDB存儲引擎支持事務(wù)菇民,其設(shè)計目標(biāo)主要面向在線事務(wù)處理 (OLTP) 的應(yīng)用尽楔。其特點是行鎖設(shè)計、支持外鍵第练,并支持類似于 Oracle 的非鎖定讀阔馋,即默認(rèn)讀取操作不會產(chǎn)生鎖。從 MySQL 數(shù)據(jù)庫 5.5.8 版本開始复旬,InnoDB 存儲引擎是默認(rèn)的存儲引擎垦缅。
? ??????InnoDB存儲引擎將數(shù)據(jù)放在一個邏輯的表空間中,這個表空間就像黑盒一樣由 InnoDB 存儲引擎自身進行管理驹碍。從 MySQL 4.1 (包括 4.1) 版本開始壁涎,它可以將每個InnoDB存儲引擎的表單獨存放到一個獨立的 ibd 文件中。此外志秃,InnoDB 存儲引擎支持用裸設(shè)備 (row disk) 用來建立其表空間怔球。
????????InnoDB 通過使用多版本并發(fā)控制 (MVCC) 來獲得高并發(fā) 性,并且實現(xiàn)了 SQL標(biāo)準(zhǔn)的 4 種隔離級別浮还,默認(rèn)為 REPEATABLE 級別竟坛。同時,使用一種被稱為 next-key locking 的策略來避免幻讀 (phantom) 現(xiàn)象的產(chǎn)生。除此之外担汤,InnoDB 儲存引擎還提供了插人緩沖 (insert buff er)涎跨、二次寫 (double write)、自適應(yīng)哈希索引 (adaptive hash index)崭歧、預(yù)讀 (read ahead) 等高性能和高可用的功能隅很。
????????對于表中數(shù)據(jù)的存儲,InnoDB 存儲引擎采用了聚集 (clustered) 的方式率碾,因此每張表的存儲都是按主鍵的順序進行存放叔营。如果沒有顯式地在表定義時指定主鍵,InnoDB 存 儲引擎會為每一行生成一個 6 字節(jié)的 ROWID, 并以此作為主鍵所宰。
1.3.2 MylSAM存儲引擎
? ??????MyISAM存儲引擎 不支持事務(wù)绒尊、表鎖設(shè)計, 支持全文索引仔粥,主要面向一些OLAP數(shù)據(jù)庫應(yīng)用婴谱。在MySQL 5.5.8版本之前MylSAM存儲引擎是默認(rèn)的存儲引擎(除Windows版本外)。數(shù)據(jù)庫系統(tǒng)與文件系統(tǒng)很大的 個不同之處在于對事務(wù)的支持躯泰,然而MyISAM存儲引擎是不支持事務(wù)的勘究。究其根本,這也不是很難理解斟冕。試想用戶是否在所有的應(yīng)用中都需要事務(wù)呢口糕?在數(shù)據(jù)倉庫中,如果沒有 ETL這些操作磕蛇, 只是簡單的報表查詢是否還需要事務(wù)的支持呢景描?此外,MylSAM存儲引擎的另一個與眾不同的地方是它 的緩沖池只 緩存(cache)索引文件秀撇,而不緩沖數(shù)據(jù)文件超棺,這點和大多數(shù)的數(shù)據(jù)庫都非常不同 。
????????MyISAM存儲引擎表由MYD和MYI組成呵燕,MYD用來存放數(shù)據(jù)文件棠绘,MYI用來存放索引文件。可以通過使用myisampack工具來進一步壓縮數(shù)據(jù)文件再扭,因為myisampack 工具使用赫夫曼(Huffma n)編碼靜態(tài)算法來壓縮數(shù)據(jù)氧苍,因此使用myisampack工具壓縮后的表是只讀的,當(dāng)然用戶也可以通過myisampack來解壓數(shù)據(jù)文件泛范。
1.3.3 NOB存儲引擎
????????NOB存儲引擎是一個集群存儲引擎让虐,類似于Oracle的RAC集群,不過與Oracle RACshare everything架構(gòu)不同的是罢荡,其結(jié)構(gòu)是 share nothing的集群架構(gòu)赡突,因此能提供更高的可用性对扶。NOB的特點是數(shù)據(jù)全部放在內(nèi)存中(從MySQL 5.1版本開始,可以將非索引數(shù)據(jù)放在 磁盤上)惭缰,因此主鍵查找(primary key lookups)的速度極快浪南,并且通過添加NOB數(shù)據(jù)存儲節(jié)點(Data Node)可以線性地提高數(shù)據(jù)庫性能,是高可用漱受、高性能的集群系統(tǒng)逞泄。
? ??????關(guān)于 NDB存儲引擎,有一個問題值得注意拜效,那就是 NDB存儲引擎的連接操作(JOIN)是在 MySQL數(shù)據(jù)庫層完成的,而不是在存儲引擎層完成的各谚。這意味著紧憾,復(fù)雜的連接操作需要巨大的網(wǎng)絡(luò)開銷,因此查詢速度很慢昌渤。如果解決了這個問題赴穗,NDB存儲引 擎的市場應(yīng)該是非常巨大的。
1.3.4 Memory存儲引擎
? ??????Memory存儲引擎( 之前稱HEAP存儲引擎)將表中的數(shù)據(jù)存放在內(nèi)存中膀息,如果數(shù)據(jù)庫重啟或發(fā)生崩潰般眉,表中的數(shù)據(jù)都將消失。它非常適合用于存儲臨時數(shù)據(jù)的臨時表潜支, 以及數(shù)據(jù)倉庫中的緯度表甸赃。Memory存儲引擎默認(rèn)使用哈希索引,而不是我們熟悉的 B+ 樹索引冗酿。
? ??????雖然Memory存儲引擎速度非巢憾裕快,但在使用上還是有一定的限制裁替。比如项玛,只支持表鎖,并發(fā)性能較差弱判,并且不支持TEXT和BLOB列類型襟沮。最重要的是,存儲變長字段(varchar)時是按照定常字段(char)的方式進行的昌腰,因此會浪費內(nèi)存开伏。
? ??????此外有一點容易被忽視,MySQL數(shù)據(jù)庫使用Memory存儲引擎作為臨時表來存放查詢的中間結(jié)果集(intermediate result)遭商。如果中間結(jié)果集大于 Memory存儲引擎表的容量設(shè)置硅则,又或者中間結(jié)果含有TEXT或BLOB列類型字段,則MySQL數(shù)據(jù)庫會把其轉(zhuǎn)換到MylSAM存儲引擎表而存放到磁盤中株婴。之前提到MyISAM不緩存數(shù)據(jù)文件怎虫,因此這時產(chǎn)生的臨時表的性能對于查詢會有損失暑认。
1.3.5 Archive存儲引擎
? ??????Archive存 儲引擎只支持 INSERT和SELECT操作,從MySQL 5.1開始支持 索 引大审。Archive存儲引擎使用zlib算法將數(shù)據(jù)行(row)進行壓縮后存儲蘸际, 壓縮比一般可達1 : 10。正如其名字所示徒扶,Archive存儲引擎非常適合存儲歸檔數(shù)據(jù)粮彤,如日志信息。 Archive存儲引擎使用行鎖來實現(xiàn)高并發(fā)的插入操作姜骡,但是其本身并不是事務(wù)安全的存 儲引擎导坟,其設(shè)計目標(biāo)主要是提供高速的插入和壓縮功能。
1.3.6 Federated存儲引擎
????????Federated存儲引擎表并不存放數(shù)據(jù)圈澈,它只是指向一臺遠程MySQL數(shù)據(jù)庫服務(wù)器上的表惫周。這非常類似于SQL Server的鏈接服務(wù)器和Oracle的透明網(wǎng)關(guān),不同的是康栈,當(dāng)前 Federated存儲引擎只支持 MySQL數(shù)據(jù)庫表递递,不支持異構(gòu)數(shù)據(jù)庫表。
1.3.7 Maria存儲引擎
????????Maria存儲引擎 是新開發(fā)的引擎啥么,設(shè)計目標(biāo)主要是用來取代原有的 MyISAM存儲引擎登舞,從而成為MySQL的默認(rèn)存儲引擎。Maria存儲引擎的開發(fā)者是MySQL的創(chuàng)始人之 一的 Michael Widenius悬荣。 因此菠秒,它可以看做是MyISAM的后續(xù)版本。Maria存儲引擎的特點是:支持緩存數(shù)據(jù)和索引文件氯迂,應(yīng)用了行鎖 設(shè)計稽煤, 提供了MVCC功能,支持事務(wù)和非事務(wù)安全的選項囚戚,以及更好的BLOB字符類型的處理性能酵熙。
1.5 連接MySQL
????????本節(jié)將介紹連接MySQL數(shù)據(jù)庫的常用方式。需要理解的是驰坊,連接MySQL操作是一個連接進程和MySQL數(shù)據(jù)庫實例進行通信匾二。從程序設(shè)計的角度來說,本質(zhì)上是進程通信拳芙。 如果對進程通信比較了解察藐,可以知道常用的進程通信方式有管道、命名管道舟扎、命名字分飞、TCP/IP套接字、UNIX域套接字睹限。MySQL數(shù)據(jù)庫提供的連接方式從本質(zhì)上看都是上述提及的進程通信方式。
1.5.1 TCP/IP
????????TCP/IP套接字方式是MySQL數(shù)據(jù)庫在任何平臺下都提供的連接方式,也是網(wǎng)絡(luò)中使用得最多的一種方式树枫。這種方式在TCP/IP連接上建立一個基于網(wǎng)絡(luò)的連接請求副砍,宏多,一般情況下客戶端(client)在一臺服務(wù)器上,而MySQL 實例(server)在另一臺服務(wù)器上,這兩臺機器通過一個TCP/IP網(wǎng)絡(luò)連接。
1.5.2 命名管道和共享內(nèi)存
????????在 Windows2000挖垛、 WindowsXP、 Windows 2003 和 Windows Vista 以及在此之上的平臺上秉颗, 如果兩個需要進程通信的進程在同一臺服務(wù)器上痢毒, 那么可以使用命名管道, Microsoft SQL Server 數(shù)據(jù)庫默認(rèn)安裝后的本地連接也是使用命名管道蚕甥。在 MySQL 數(shù)據(jù)庫中須在配置文件中啟用 --enable-named-pipe 選項哪替。 在 MySQL 4.1 之后的版本中, MySQL 還提供了 共享內(nèi)存的連接方式梢灭, 這是通過在配置文件中添加 --shared-memory 實現(xiàn)的。 如果想使用 共享內(nèi)存的方式蒸其, 在連接時敏释, MySQL 客戶端還必須使用 --protocol=memory 選項。
1.5.3 UNIX 域套接字
? ??????在Linux和UNIX環(huán)境下摸袁, 還可以使用UNIX域套接字钥顽。UNIX域套接字其實不是一個網(wǎng)絡(luò)協(xié)議, 所以只能在 MySQL 客戶端和數(shù)據(jù)庫實例在一臺服務(wù)器上的情況下使用靠汁。 用戶可以在配置文件中指定套接字文件的路徑蜂大。