《Oracle9i&10g編程藝術》讀后感
《Oracle9i&10g編程藝術--深入數據庫體系結構》即為《Expert one to one oracle》的升級版本,不過升級后可能會變為三本書,這本書強調的是深入數據庫體系結構的講解,本書的作者Thomas Kyte(即Tom)無疑是Oracle界最為知名的人物,而這本書可以說基本是專為開發人員而寫的,因為我個人覺得書中講的東西大部分DBA都是懂的,但對于開發人員來講估計大部分都不懂,Thomas Kyte抓住了怎么給開發人員講才能講清的方法,對于書中的每項內容Thomas會講解什么時候這么做、為什么要這么做、什么時候不能這么做以及為什么不這么做,要說服開發人員,很多時候除了告訴怎么做以外,還必須得告訴為什么要這么做,否則很難說服,而Tom在書中則很好的做到了這點,Tom會告訴你Oracle是怎么去實現的,所以你要這么做或者不能這么做,這本書除了讓我學習到了更多的Oracle知識外,還讓我更加明白了數據庫在系統中的重要性以及充分發揮數據庫的功能是多么重要的一件事,還有一個附加的好處就是讓我們可以窺探到部分Oracle的設計,對于自己實現應用系統也是會找到一些可參考的地方,這本書寫的實在是太好了,強烈推薦給開發人員看。
按照書中所講的東西,個人覺得開發人員對于數據庫應了解如下內容:
1、讀一致性
Oracle在讀數據時采用的是保證數據一致的方法,也就是說查詢出的所有數據均為發起查詢時的數據,Oracle這么做的主要原因是為了避免讀阻塞寫,這么設計的目的是為了支持高并發,而其他的數據庫有些不是這么做的,就像在sql server中需要明確的在查詢語句中加上with nolock才會避免讀阻塞寫。
以一個這樣的例子來說明下oracle的讀一致性:
假設現在有一張賬戶表,來看看同時進行的一個轉賬動作和查詢動作:
查詢動作:查詢所有賬戶的money的總數;
轉賬動作:從A賬戶轉400到B賬戶。
查詢到A賬戶的money為:600
更新A賬戶的錢為200
查詢到C賬戶的money為:100
更新B賬戶的錢為500+400
提交。
此時查詢才查詢到B賬戶,那么
這個時候查詢到的B賬戶的money到底是500還是900呢?
按照oracle的讀一致性非常明顯這個時候查詢到的B賬戶的money會是500,這就是讀一致性的概念,在其他的讀會阻塞寫的數據庫中確實不會出現這樣的疑問(因為轉賬的動作得等到查詢動作結束后才能執行),但那樣的方式很大程度降低了數據庫的可并發性,在后面的redo&undo中會講講oracle的這種讀一致性是怎么實現的。
2、鎖機制
Oracle主要有行級鎖和表級鎖,大多數情況下Oracle都只會出現行級鎖,很少會出現表級鎖,所以在oracle中出現死鎖的現象還是非常少的,開發人員在設計系統時應盡量避免等待行鎖的現象,也就是避免多人共同修改同一行,只要解決了這種現象,其實也就意味著Oracle支持高并發是完全沒有任何問題的,關于鎖定機制最容易出現的問題就是丟失更新這個問題了。
3、丟失更新
丟失更新的實際例子就是:A、B均已讀出數據并開始進行修改,當A提交數據后,B再提交就出現了B覆蓋掉A修改的內容的情況。
丟失更新的解決方法通常都是采用版本列、時間戳列這樣的方法來實現,不過只有在多并發共同修改同一行的系統中才需要慎重的考慮這個問題。
4、索引
索引無疑是數據庫中非常重要的機制,盡管這個更多的可以交給DBA來進行調優設計,不過開發人員還是要大概的有所了解,至少要知道索引有哪幾種(B樹索引、函數索引、bitmap索引、聚簇索引、對部分行建索引等),什么場合下適合用哪種索引。
Tom在書中強調了很多次,沒有"fast=true"這種銀彈式的提速開關,只能是根據實際情況來分析,也就是說不是說只要加了索引性能就會提升的,索引主要是為了查詢大表中的少量數據的,Tom在書中講解了索引的查找數據的方法(索引中映射到的為rowid,在查找到索引后查找數據時oracle是根據每個rowid去表存儲的塊中讀取的),按照其查找數據的方法完全有可能出現查找索引比全表掃描還慢的現象,舉例來說明下:
假設一張表有100,000行記錄,現在我們要讀取其中的20,000行,假設每行的大小約為80字節,數據庫的塊大小為8k,在這種情況下表中的記錄大約會產生1000個塊,那么這個時候使用索引讀取的話就要做20,000次Table access by rowid,而整個表都只有1000個塊,也就是說即使全表掃描也只需要做1000次的動作,但現在竟然要做20,000次,自然慢多了。
索引還和物理組織呀、聚簇因子呀等等都有關系。
5、Oracle文件
Oracle文件主要有服務器參數文件、數據文件、控制文件、密碼文件、在線日志文件等等,這些開發人員也應該大概的了解下。
6、事務
事務對于并發系統而言也是非常重要的機制,所以開發人員要對這塊比較了解,Oracle建議是否提交事務要根據數據邏輯的完整性來決定,而不是說越快提交越好,oracle會保證語句級的原子性(例如執行語句時的觸發器、存儲過程都會控制在統一的事務范圍),同時oracle還支持像分布式事務、自治事務等。
對于開發人員而言,要把握的就是什么時候提交事務,應該注意的就是事務應該控制在自己手里來決定什么時候提交,像對于使用jdbc的java開發人員而言,要注意,jdbc默認是執行一條就提交一條的。
7、redo&undo
redo和undo絕對是oracle中非常重要的兩個東西,redo用來記錄所有的操作,以便oracle在遇到斷電等等意外的情況下也可準確的恢復實例和之前的動作,而undo則是用來記錄所有的操作的逆動作,以支持像回滾、讀一致性這樣的操作,從這里我們就可以知道當undo設置的太小或查詢執行時間太長的時候,就可能會出現snapshoot too old這種錯誤。
從這個章節中還得學會評估redo、undo產生的大小,另外就是遵循Tom所說的生產環境一定要是archivelog模式的,否則數據丟了也就只能哭了。
8、數據庫表
要了解下oracle中的堆組織表、索引組織表、聚簇索引表等幾種表的形式。
9、數據類型
要了解下oracle中的varchar2、number、lob這些類型。
10、表和索引分區
應該了解oracle支持哪幾種表和索引分區,什么時候用,怎么去用,開發人員要了解的原因是其實表和索引分區要高效的使用是得根據業務分析來形成的,隨意的表和索引分區很有可能會造成性能下降。
這些方面應該是開發人員至少應該了解的,在數據庫方面的開發上開發人員最應該關注的就是基本的SQL編寫優化法則、并發和鎖的控制機制、事務使用機制,因為對于開發而言,會帶來挑戰的就是在并發的情況下,設計人員則應根據數據庫的并發實現機制來盡量減少鎖等待的現象,其他的調優工作可以由DBA來完成,但開發人員也應該提供輔助,像表分區的做法等等。
根據Tom在書中描述的數據庫的鎖機制、并發機制等等,可以看出每種數據庫在實現這些方面都是不一樣的,所以要做到數據庫獨立性其實是不可能的,就像Tom說的,付出了那么高的價格買下了數據庫,難道你就只是把它當成一個簡單的文件系統而使用,而不去充分使用/發揮它的功能,因為很多時候你付出了巨大努力實現的東西對于數據庫而言也許就只是簡單的一句話而已,所以從此我對數據庫獨立性也say NO!,即使是使用Hibernate這種相對來講可以使數據庫獨立的東西,幾個簡單的例子來說明在數據庫切換時要做的工作:
1、is null和字段=null
在Oracle和SQL Server中采用的均為is null,而在有些數據庫里采用的則是字段=null的方式來獲取。
2、函數
例如sql server的dateadd、identity這些,到了oracle中自然要切換。
3、鎖機制
這個是最麻煩的,就像你在oracle中可以使用select而不必擔心讀會阻塞寫,但在sql server中就得帶上with nolock。
4、事務
雖然表面看起來事務類型都是一樣的,但各種數據庫實現事務機制方法的不同決定了在切換的時候還得考慮事務使用上是不是要修改。
對于1、2兩點你可以盡量的避免,3、4兩點則是無法避免的,所以在是使用數據庫上不用過多的去考慮數據庫獨立性的實現,當然,這并不意味著hibernate這些ORM的東西就不需要了,:),我倒是一直非常希望有哪個ORM工具能透明實現數據庫的切換,包括上面所說的那些機制的自動轉換,但這相對而言幾乎是不可能的,因為要對每種數據庫都精通才能做得到。
按照書中所講的東西,個人覺得開發人員對于數據庫應了解如下內容:
1、讀一致性
Oracle在讀數據時采用的是保證數據一致的方法,也就是說查詢出的所有數據均為發起查詢時的數據,Oracle這么做的主要原因是為了避免讀阻塞寫,這么設計的目的是為了支持高并發,而其他的數據庫有些不是這么做的,就像在sql server中需要明確的在查詢語句中加上with nolock才會避免讀阻塞寫。
以一個這樣的例子來說明下oracle的讀一致性:
假設現在有一張賬戶表,來看看同時進行的一個轉賬動作和查詢動作:
查詢動作:查詢所有賬戶的money的總數;
轉賬動作:從A賬戶轉400到B賬戶。
查詢到A賬戶的money為:600
更新A賬戶的錢為200
查詢到C賬戶的money為:100
更新B賬戶的錢為500+400
提交。
此時查詢才查詢到B賬戶,那么
這個時候查詢到的B賬戶的money到底是500還是900呢?
按照oracle的讀一致性非常明顯這個時候查詢到的B賬戶的money會是500,這就是讀一致性的概念,在其他的讀會阻塞寫的數據庫中確實不會出現這樣的疑問(因為轉賬的動作得等到查詢動作結束后才能執行),但那樣的方式很大程度降低了數據庫的可并發性,在后面的redo&undo中會講講oracle的這種讀一致性是怎么實現的。
2、鎖機制
Oracle主要有行級鎖和表級鎖,大多數情況下Oracle都只會出現行級鎖,很少會出現表級鎖,所以在oracle中出現死鎖的現象還是非常少的,開發人員在設計系統時應盡量避免等待行鎖的現象,也就是避免多人共同修改同一行,只要解決了這種現象,其實也就意味著Oracle支持高并發是完全沒有任何問題的,關于鎖定機制最容易出現的問題就是丟失更新這個問題了。
3、丟失更新
丟失更新的實際例子就是:A、B均已讀出數據并開始進行修改,當A提交數據后,B再提交就出現了B覆蓋掉A修改的內容的情況。
丟失更新的解決方法通常都是采用版本列、時間戳列這樣的方法來實現,不過只有在多并發共同修改同一行的系統中才需要慎重的考慮這個問題。
4、索引
索引無疑是數據庫中非常重要的機制,盡管這個更多的可以交給DBA來進行調優設計,不過開發人員還是要大概的有所了解,至少要知道索引有哪幾種(B樹索引、函數索引、bitmap索引、聚簇索引、對部分行建索引等),什么場合下適合用哪種索引。
Tom在書中強調了很多次,沒有"fast=true"這種銀彈式的提速開關,只能是根據實際情況來分析,也就是說不是說只要加了索引性能就會提升的,索引主要是為了查詢大表中的少量數據的,Tom在書中講解了索引的查找數據的方法(索引中映射到的為rowid,在查找到索引后查找數據時oracle是根據每個rowid去表存儲的塊中讀取的),按照其查找數據的方法完全有可能出現查找索引比全表掃描還慢的現象,舉例來說明下:
假設一張表有100,000行記錄,現在我們要讀取其中的20,000行,假設每行的大小約為80字節,數據庫的塊大小為8k,在這種情況下表中的記錄大約會產生1000個塊,那么這個時候使用索引讀取的話就要做20,000次Table access by rowid,而整個表都只有1000個塊,也就是說即使全表掃描也只需要做1000次的動作,但現在竟然要做20,000次,自然慢多了。
索引還和物理組織呀、聚簇因子呀等等都有關系。
5、Oracle文件
Oracle文件主要有服務器參數文件、數據文件、控制文件、密碼文件、在線日志文件等等,這些開發人員也應該大概的了解下。
6、事務
事務對于并發系統而言也是非常重要的機制,所以開發人員要對這塊比較了解,Oracle建議是否提交事務要根據數據邏輯的完整性來決定,而不是說越快提交越好,oracle會保證語句級的原子性(例如執行語句時的觸發器、存儲過程都會控制在統一的事務范圍),同時oracle還支持像分布式事務、自治事務等。
對于開發人員而言,要把握的就是什么時候提交事務,應該注意的就是事務應該控制在自己手里來決定什么時候提交,像對于使用jdbc的java開發人員而言,要注意,jdbc默認是執行一條就提交一條的。
7、redo&undo
redo和undo絕對是oracle中非常重要的兩個東西,redo用來記錄所有的操作,以便oracle在遇到斷電等等意外的情況下也可準確的恢復實例和之前的動作,而undo則是用來記錄所有的操作的逆動作,以支持像回滾、讀一致性這樣的操作,從這里我們就可以知道當undo設置的太小或查詢執行時間太長的時候,就可能會出現snapshoot too old這種錯誤。
從這個章節中還得學會評估redo、undo產生的大小,另外就是遵循Tom所說的生產環境一定要是archivelog模式的,否則數據丟了也就只能哭了。
8、數據庫表
要了解下oracle中的堆組織表、索引組織表、聚簇索引表等幾種表的形式。
9、數據類型
要了解下oracle中的varchar2、number、lob這些類型。
10、表和索引分區
應該了解oracle支持哪幾種表和索引分區,什么時候用,怎么去用,開發人員要了解的原因是其實表和索引分區要高效的使用是得根據業務分析來形成的,隨意的表和索引分區很有可能會造成性能下降。
這些方面應該是開發人員至少應該了解的,在數據庫方面的開發上開發人員最應該關注的就是基本的SQL編寫優化法則、并發和鎖的控制機制、事務使用機制,因為對于開發而言,會帶來挑戰的就是在并發的情況下,設計人員則應根據數據庫的并發實現機制來盡量減少鎖等待的現象,其他的調優工作可以由DBA來完成,但開發人員也應該提供輔助,像表分區的做法等等。
根據Tom在書中描述的數據庫的鎖機制、并發機制等等,可以看出每種數據庫在實現這些方面都是不一樣的,所以要做到數據庫獨立性其實是不可能的,就像Tom說的,付出了那么高的價格買下了數據庫,難道你就只是把它當成一個簡單的文件系統而使用,而不去充分使用/發揮它的功能,因為很多時候你付出了巨大努力實現的東西對于數據庫而言也許就只是簡單的一句話而已,所以從此我對數據庫獨立性也say NO!,即使是使用Hibernate這種相對來講可以使數據庫獨立的東西,幾個簡單的例子來說明在數據庫切換時要做的工作:
1、is null和字段=null
在Oracle和SQL Server中采用的均為is null,而在有些數據庫里采用的則是字段=null的方式來獲取。
2、函數
例如sql server的dateadd、identity這些,到了oracle中自然要切換。
3、鎖機制
這個是最麻煩的,就像你在oracle中可以使用select而不必擔心讀會阻塞寫,但在sql server中就得帶上with nolock。
4、事務
雖然表面看起來事務類型都是一樣的,但各種數據庫實現事務機制方法的不同決定了在切換的時候還得考慮事務使用上是不是要修改。
對于1、2兩點你可以盡量的避免,3、4兩點則是無法避免的,所以在是使用數據庫上不用過多的去考慮數據庫獨立性的實現,當然,這并不意味著hibernate這些ORM的東西就不需要了,:),我倒是一直非常希望有哪個ORM工具能透明實現數據庫的切換,包括上面所說的那些機制的自動轉換,但這相對而言幾乎是不可能的,因為要對每種數據庫都精通才能做得到。
posted on 2007-08-10 12:20 BlueDavy 閱讀(4361) 評論(3) 編輯 收藏 所屬分類: 業界隨想