一、關系型數據庫
關系型數據庫,是指采用了關系模型來組織數據的數據庫。關系模型是在1970年由IBM的研究員E.F.Codd博士首先提出的,在之后的幾十年中,關系模型的概念得到了充分的發展並逐漸成為主流數據庫結構的主流模型。
簡單來說,關系模型指的就是二維表格模型,而一個關系型數據庫就是由二維表及其之間的聯系所組成的一個數據組織。關系模型中常用的概念:
關系:可以理解為一張二維表,每個關系都具有一個關系名,就是通常說的表名
元組:可以理解為二維表中的一行,在數據庫中經常被稱為記錄
屬性:可以理解為二維表中的一列,在數據庫中經常被稱為字段
域:屬性的取值范圍,也就是數據庫中某一列的取值限制
關鍵字:一組可以唯一標識元組的屬性,數據庫中常稱為主鍵,由一個或多個列組成
關系模式:指對關系的描述。其格式為:關系名(屬性1,屬性2, ... ... ,屬性N),在數據庫中成為表結構
關系型數據庫的優點:
容易理解:二維表結構是非常貼近邏輯世界的一個概念,關系模型相對網狀、層次等其他模型來說更容易理解使用方便:通用的SQL語言使得操作關系型數據庫非常方便
易於維護:豐富的完整性(實體完整性、參照完整性和用戶定義的完整性)大大減低了數據冗余和數據不一致的概率
關系型數據庫瓶頸
1).高並發讀寫需求
網站的用戶並發性非常高,往往達到每秒上萬次讀寫請求,對於傳統關系型數據庫來說,硬盤I/O是一個很大的瓶頸2).海量數據的高效率讀寫
網站每天產生的數據量是巨大的,對於關系型數據庫來說,在一張包含海量數據的表中查詢,效率是非常低的3).高擴展性和可用性
在基於web的結構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,數據庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬件和服務節點來擴展性能和負載能力。對於很多需要提供24小時不間斷服務的網站來說,對數據庫系統進行升級和擴展是非常痛苦的事情,往往需要停機維護和數據遷移。- 事務一致性: 關系型數據庫在對事物一致性的維護中有很大的開銷,而現在很多web2.0系統對事物的讀寫一致性都不高
- 讀寫實時性: 對關系數據庫來說,插入一條數據之后立刻查詢,是肯定可以讀出這條數據的,但是對於很多web應用來說,並不要求這么高的實時性,比如發一條消息之后,過幾秒乃至十幾秒之后才看到這條動態是完全可以接受的
- 復雜SQL,特別是多表關聯查詢: 任何大數據量的web系統,都非常忌諱多個大表的關聯查詢,以及復雜的數據分析類型的復雜SQL報表查詢,特別是SNS類型的網站(SNS,專指社交網絡服務,包括了社交軟件和社交網站。),從需求以及產品階級角度,就避免了這種情況的產生。往往更多的只是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能極大的弱化了
二、NoSQL
NoSQL一詞首先是Carlo Strozzi在1998年提出來的,指的是他開發的一個沒有SQL功能,輕量級的,開源的關系型數據庫。這個定義跟我們現在對NoSQL的定義有很大的區別,它確確實實字如其名,指的就是“沒有SQL”的數據庫。但是NoSQL的發展慢慢偏離了初衷,我們要的不是“no sql”,而是“no relational”,也就是我們現在常說的非關系型數據庫了。2009年初,Johan Oskarsson舉辦了一場關於開源分布式數據庫的討論,Eric Evans在這次討論中再次提出了NoSQL一詞,用於指代那些非關系型的,分布式的,且一般不保證遵循ACID原則的數據存儲系統。Eric Evans使用NoSQL這個詞,並不是因為字面上的“沒有SQL”的意思,他只是覺得很多經典的關系型數據庫名字都叫“**SQL”,所以為了表示跟這些關系型數據庫在定位上的截然不同,就是用了“NoSQL“一詞。注:數據庫事務必須具備ACID特性,ACID是Atomic原子性,Consistency一致性,Isolation隔離性,Durability持久性。
非關系型數據庫提出另一種理念,例如,以鍵值對存儲,且結構不固定,每一個元組可以有不一樣的字段,每個元組可以根據需要增加一些自己的鍵值對,這樣就不會局限於固定的結構,可以減少一些時間和空間的開銷。使用這種方式,用戶可以根據需要去添加自己需要的字段,這樣,為了獲取用戶的不同信息,不需要像關系型數據庫中,要對多表進行關聯查詢。僅需要根據id取出相應的value就可以完成查詢。但非關系型數據庫由於很少的約束,他也不能夠提供像SQL所提供的where這種對於字段屬性值情況的查詢。並且難以體現設計的完整性。他只適合存儲一些較為簡單的數據,對於需要進行較復雜查詢的數據,SQL數據庫顯的更為合適。
2-1.非關系型數據庫分類
由於非關系型數據庫本身天然的多樣性,以及出現的時間較短,因此,不想關系型數據庫,有幾種數據庫能夠一統江山,非關系型數據庫非常多,並且大部分都是開源的。這些數據庫中,其實實現大部分都比較簡單,除了一些共性外,很大一部分都是針對某些特定的應用需求出現的,因此,對於該類應用,具有極高的性能。依據結構化方法以及應用場合的不同,主要分為以下幾類:
1).面向高性能並發讀寫的key-value數據庫:key-value數據庫的主要特點即使具有極高的並發讀寫性能,Redis,Tokyo Cabinet,Flare就是這類的代表
2).面向海量數據訪問的面向文檔數據庫:這類數據庫的特點是,可以在海量的數據中快速的查詢數據,典型代表為MongoDB以及CouchDB
3).面向可擴展性的分布式數據庫:這類數據庫想解決的問題就是傳統數據庫存在可擴展性上的缺陷,這類數據庫可以適應數據量的增加以及數據結構的變化
三. 關系型數據庫 V.S. 非關系型數據庫
關系型數據庫的最大特點就是事務的一致性:傳統的關系型數據庫讀寫操作都是事務的,具有ACID的特點,這個特性使得關系型數據庫可以用於幾乎所有對一致性有要求的系統中,如典型的銀行系統。但是,在網頁應用中,尤其是SNS應用中,一致性卻不是顯得那么重要,用戶A看到的內容和用戶B看到同一用戶C內容更新不一致是可以容忍的,或者說,兩個人看到同一好友的數據更新的時間差那么幾秒是可以容忍的,因此,關系型數據庫的最大特點在這里已經無用武之地,起碼不是那么重要了。
相反地,關系型數據庫為了維護一致性所付出的巨大代價就是其讀寫性能比較差,而像微博、facebook這類SNS的應用,對並發讀寫能力要求極高,關系型數據庫已經無法應付(在讀方面,傳統上為了克服關系型數據庫缺陷,提高性能,都是增加一級memcache來靜態化網頁,而在SNS中,變化太快,memchache已經無能為力了),因此,必須用新的一種數據結構存儲來代替關系數據庫。
關系數據庫的另一個特點就是其具有固定的表結構,因此,其擴展性極差,而在SNS中,系統的升級,功能的增加,往往意味着數據結構巨大變動,這一點關系型數據庫也難以應付,需要新的結構化數據存儲。
於是,非關系型數據庫應運而生,由於不可能用一種數據結構化存儲應付所有的新的需求,因此,非關系型數據庫嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合。 必須強調的是,數據的持久存儲,尤其是海量數據的持久存儲,還是需要一種關系數據庫這員老將。
1.存儲方式
關系型數據庫是表格式的,因此存儲在表的行和列中。他們之間很容易關聯協作存儲,提取數據很方便。而Nosql數據庫則與其相反,他是大塊的組合在一起。通常存儲在數據集中,就像文檔、鍵值對或者圖結構。
2.存儲結構
關系型數據庫對應的是結構化數據,數據表都預先定義了結構(列的定義),結構描述了數據的形式和內容。這一點對數據建模至關重要,雖然預定義結構帶來了可靠性和穩定性,但是修改這些數據比較困難。而Nosql數據庫基於動態結構,使用與非結構化數據。因為Nosql數據庫是動態結構,可以很容易適應數據類型和結構的變化。
3.存儲規范
關系型數據庫的數據存儲為了更高的規范性,把數據分割為最小的關系表以避免重復,獲得精簡的空間利用。雖然管理起來很清晰,但是單個操作設計到多張表的時候,數據管理就顯得有點麻煩。而Nosql數據存儲在平面數據集中,數據經常可能會重復。單個數據庫很少被分隔開,而是存儲成了一個整體,這樣整塊數據更加便於讀寫
4.存儲擴展
這可能是兩者之間最大的區別,關系型數據庫是縱向擴展,也就是說想要提高處理能力,要使用速度更快的計算機。因為數據存儲在關系表中,操作的性能瓶頸可能涉及到多個表,需要通過提升計算機性能來克服。雖然有很大的擴展空間,但是最終會達到縱向擴展的上限。而Nosql數據庫是橫向擴展的,它的存儲天然就是分布式的,可以通過給資源池添加更多的普通數據庫服務器來分擔負載。
橫向擴展是已擴展服務器的數量進行高並發的處理(增強處理業務的能力)
根據配置nginx的反向代理,轉發服務器(配置的ip)進行輪換處理業務(可加入負載均衡器進行分發請求)
縱向擴展,是增加單機的處理能力,一般增加cpu的處理能力
5.查詢方式
關系型數據庫通過結構化查詢語言來操作數據庫(就是我們通常說的SQL)。SQL支持數據庫CURD操作的功能非常強大,是業界的標准用法。而Nosql查詢以塊為單元操作數據,使用的是非結構化查詢語言(UnQl),它是沒有標准的。關系型數據庫表中主鍵的概念對應Nosql中存儲文檔的ID。關系型數據庫使用預定義優化方式(比如索引)來加快查詢操作,而Nosql更簡單更精確的數據訪問模式。
6.事務
關系型數據庫遵循ACID規則(原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)),而Nosql數據庫遵循BASE原則(基本可用(Basically Availble)、軟/柔性事務(Soft-state )、最終一致性(Eventual Consistency))。由於關系型數據庫的數據強一致性,所以對事務的支持很好。關系型數據庫支持對事務原子性細粒度控制,並且易於回滾事務。而Nosql數據庫是在CAP(一致性、可用性、分區容忍度)中任選兩項,因為基於節點的分布式系統中,很難全部滿足,所以對事務的支持不是很好,雖然也可以使用事務,但是並不是Nosql的閃光點。
柔性事務滿足Base理論(基本可用、最終一致性)、CAP理論。
剛性事務滿足ACID理論。
1. 原子性
原子性是指事務是一個不可再分割的工作單元,事務中的操作要么都發生,要么都不發生。
可采用“A向B轉賬”這個例子來說明解釋
在DBMS中,默認情況下一條SQL就是一個單獨事務,事務是自動提交的。只有顯式的使用start transaction開啟一個事務,才能將一個代碼塊放在事務中執行。
2. 一致性
一致性是指在事務開始之前和事務結束以后,數據庫的完整性約束沒有被破壞。這是說數據庫事務不能破壞關系數據的完整性以及業務邏輯上的一致性。
如A給B轉賬,不論轉賬的事務操作是否成功,其兩者的存款總額不變(這是業務邏輯的一致性,至於數據庫關系約束的完整性就更好理解了)。
保障機制(也從兩方面着手):數據庫層面會在一個事務執行之前和之后,數據會符合你設置的約束(唯一約束,外鍵約束,check約束等)和觸發器設置;此外,數據庫的內部數據結構(如 B 樹索引或雙向鏈表)都必須是正確的。業務的一致性一般由開發人員進行保證,亦可轉移至數據庫層面。
3. 隔離性
多個事務並發訪問時,事務之間是隔離的,一個事務不應該影響其它事務運行效果。
在並發環境中,當不同的事務同時操縱相同的數據時,每個事務都有各自的完整數據空間。由並發事務所做的修改必須與任何其他並發事務所做的修改隔離。事務查看數據更新時,數據所處的狀態要么是另一事務修改它之前的狀態,要么是另一事務修改它之后的狀態,事務不會查看到中間狀態的數據。
事務最復雜問題都是由事務隔離性引起的。完全的隔離性是不現實的,完全的隔離性要求數據庫同一時間只執行一條事務,這樣會嚴重影響性能。
關於隔離性中的事務隔離等級(事務之間影響),參見相應博文
4. 持久性
這是最好理解的一個特性:持久性,意味着在事務完成以后,該事務所對數據庫所作的更改便持久的保存在數據庫之中,並不會被回滾。(完成的事務是系統永久的部分,對系統的影響是永久性的,該修改即使出現致命的系統故障也將一直保持)
write ahead logging:SQL Server中使用了WAL(Write-Ahead Logging)技術來保證事務日志的ACID特性,在數據寫入到數據庫之前,先寫入到日志,再將日志記錄變更到存儲器中。
7.性能
關系型數據庫為了維護數據的一致性付出了巨大的代價,讀寫性能比較差。在面對高並發讀寫性能非常差,面對海量數據的時候效率非常低。而Nosql存儲的格式都是key-value類型的,並且存儲在內存中,非常容易存儲,而且對於數據的 一致性是 弱要求。Nosql無需sql的解析,提高了讀寫性能。
8.授權方式
關系型數據庫通常有SQL Server,Mysql,Oracle。主流的Nosql數據庫有redis,memcache,MongoDb。大多數的關系型數據庫都是付費的並且價格昂貴,成本較大,而Nosql數據庫通常都是開源的。
oracle與mysql的區別
一、並發性
並發性是數據庫最重要的特性,但並發涉及到資源的獲取、共享與鎖定。mysql:mysql以表級鎖為主,對資源鎖定的粒度很大,如果一個session對一個表加鎖時間過長,會讓其他session無法更新此表中的數據。雖然InnoDB引擎的表可以用行級鎖,但這個行級鎖的機制依賴於表的索引,如果表沒有索引,或者sql語句沒有使用索引,那么仍然使用表級鎖。
oracle:oracle使用行級鎖,對資源鎖定的粒度要小很多,只是鎖定sql需要的資源,並且加鎖是在數據庫中的數據行上,不依賴與索引。所以oracle對並發性的支持要好很多。
二、一致性
oracle:oracle支持serializable的隔離級別,可以實現最高級別的讀一致性。每個session提交后其他session才能看到提交的更改。oracle通過在undo表空間中構造多版本數據塊來實現讀一致性,每個session查詢時,如果對應的數據塊發生變化,oracle會在undo表空間中為這個session構造它查詢時的舊的數據塊。mysql:mysql沒有類似oracle的構造多版本數據塊的機制,只支持read commited的隔離級別。一個session讀取數據時,其他session不能更改數據,但可以在表最后插入數據。session更新數據時,要加上排它鎖,其他session無法訪問數據。
三、事務
oracle很早就完全支持事務。mysql在innodb存儲引擎的行級鎖的情況下才支持事務。
四、數據持久性
oracle:保證提交的數據均可恢復,因為oracle把提交的sql操作線寫入了在線聯機日志文件中,保持到了磁盤上,如果出現數據庫或主機異常重啟,重啟后oracle可以考聯機在線日志恢復客戶提交的數據。mysql:默認提交sql語句,但如果更新過程中出現db或主機重啟的問題,也許會丟失數據。
五、提交方式
oracle默認不自動提交,需要用戶手動提交。mysql默認是自動提交。
六、邏輯備份
oracle邏輯備份時不鎖定數據,且備份的數據是一致的。mysql邏輯備份時要鎖定數據,才能保證備份的數據是一致的,影響業務正常的dml使用。
七、熱備份
oracle有成熟的熱備工具rman,熱備時,不影響用戶使用數據庫。即使備份的數據庫不一致,也可以在恢復時通過歸檔日志和聯機重做日志進行一致的回復。mysql:myisam的引擎,用mysql自帶的mysqlhostcopy熱備時,需要給表加讀鎖,影響dml操作。innodb的引擎,它會備份innodb的表和索引,但是不會備份.frm文件。用ibbackup備份時,會有一個日志文件記錄備份期間的數據變化,因此可以不用鎖表,不影響其他用戶使用數據庫。但此工具是收費的。innobackup是結合ibbackup使用的一個腳本,他會協助對.frm文件的備份。
八、sql語句的擴展和靈活性
mysql對sql語句有很多非常實用而方便的擴展,比如limit功能,insert可以一次插入多行數據,select某些管理數據可以不加from。oracle在這方面感覺更加穩重傳統一些。
九、復制
oracle:既有推或拉式的傳統數據復制,也有dataguard的雙機或多機容災機制,主庫出現問題是,可以自動切換備庫到主庫,但配置管理較復雜。mysql:復制服務器配置簡單,但主庫出問題時,叢庫有可能丟失一定的數據。且需要手工切換叢庫到主庫。
十、性能診斷
oracle有各種成熟的性能診斷調優工具,能實現很多自動分析、診斷功能。比如awr、addm、sqltrace、tkproof等mysql的診斷調優方法較少,主要有慢查詢日志。
十一、權限與安全
mysql的用戶與主機有關,感覺沒有什么意義,另外更容易被仿冒主機及ip有可乘之機。oracle的權限與安全概念比較傳統,中規中矩。十二、分區表和分區索引
oracle的分區表和分區索引功能很成熟,可以提高用戶訪問db的體驗。
mysql的分區表還不太成熟穩定。
十三、管理工具
oracle有多種成熟的命令行、圖形界面、web管理工具,還有很多第三方的管理工具,管理極其方便高效。mysql管理工具較少,在linux下的管理工具的安裝有時要安裝額外的包(phpmyadmin, etc),有一定復雜性。
