Vincent Jia 博客

          to be a better man, to be a bad man.

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            29 隨筆 :: 3 文章 :: 0 評論 :: 0 Trackbacks

          #

          “開-閉”原則 (Open-Closed principle, OCP)

           

          一個軟件實體應當對擴展開放,對修改關閉。

          Software entities should be open for extension, but closed for modification.

          在設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展。

           

          “可變性的封裝原則”從工程的角度講解了如何實現“開-閉”原則。

             “可變性的封裝原則”意味著兩點:

          1.一種可變性不應當散落在代碼的很多角落里,而應當被封裝到一個對象里面。繼承應當被看做是封裝變化的方法,而不應當被認為是從一般的對象生成特殊的對象方法。

          2.一種可變性不應當與另一種可變性混合在一起。所有的類圖的繼承結構一般不會超過兩層,不然就意味著將兩種不同的可變性混合在一起。

           

          “開-閉”原則與其他原則的關系:

           

          里氏代換原則是,任何基類可以出現的地方,子類一定可以出現。

          里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化,而基類與子類的繼承關系就是抽象化的具體體現,所以里氏代換原則是對實現抽象化的具體步驟的規范。違反里氏代換原則的,也違背“開-閉”原則,反之不一定成立。

           

          依賴倒轉原則是,要依賴于抽象,不要依賴于實現。

          “開-閉”原則是目標,依賴倒轉原則是手段。

           

          合成/聚合復用原則是,要盡量使用合成/聚合,而不是繼承關系達到復用的目的。

          合成/聚合復用原則與里氏代換原則相輔相成,兩者都是實現“開-閉”原則的具體步驟的規范。

           

          迪米特法則是,一個軟件實體應當與盡可能少的其他實體發生相互作用。

          一個遵守迪米特原則設計出來的系統在功能需要擴展時,會相對更容易地做到對修改的關閉。

           

          接口隔離原則是,應當為客戶端提供盡可能小的單獨的接口,而不是提供大的總接口。

          接口隔離原則與廣義的迪米特法則都是對一個軟件實體與其他的軟件實體的通信的限制。遵循接口隔離原則,會使一個軟件系統在功能擴展的過程當中,不會將修改的壓力傳遞到其他的對象。

           

          一個重構方法的討論

           

          “將條件轉移語句改寫成為多態性”是一條廣為流傳的代碼重構做法。

          這一做法本身并不能保證“開-閉”原則,應當以“開-閉”原則判斷是否需要改寫成多態。條件轉移并不是錯誤,如果需要,完全可以選擇使用條件轉移。

          如果一個條件轉移語句確實封裝了某種商務邏輯的可變性,那么將此種可變性封裝起來就符合“開-閉”原則設計思想了。如果一個條件轉移語句沒有涉及重要的商務邏輯,或者不會隨著時間的變化而變化,也不意味著任何的可擴展性,那么它就沒有涉及任何有意義的可變性。這時候將這個條件轉移語句改寫成多態性就是一種沒有意義的浪費。

           

          抽象類應當擁有盡可能多的共同代碼

           在一個繼承的等級結構中,共同的代碼應當盡量向等級結構的上方移動。把重復的代碼從子類里面移動到超類里面,可以提高代碼的復用率。在代碼發生改變時,設計師之需要修改一個地方。

           

          抽象類應當擁有盡可能少的數據

          與代碼的移動方向相反,數據的移動方向是從抽象類到具體類,向等級結構的下方移動。一個對象的數據不論是否使用都會占用資源,所以應當放到等級結構的低端。

           

          什么時候才應當使用繼承復用

          1.子類是超類的一個特殊種類,而不是超類的一個角色,Is-A才符合繼承關系。

          2.永遠不會出現需要將子類換成另一個類的子類的情況。

          3.子類具有擴展超類的責任,而不是具有置換掉(Override)和注銷掉(Nullify)超類的責任。

          4.只有在分類學角度上有意義時,才可以使用繼承,不要從工具類繼承。


          轉載自:“開-閉”原則 (Open-Closed principle, OCP)
          posted @ 2011-12-08 16:51 iLinux 閱讀(205) | 評論 (0)編輯 收藏

          前段時間系統升級時遭遇了OOM,具體解決過程見 遭遇OutOfMemoryError
          為了鞏固對于java啟動各項參數的認識,決定將所有參數列舉出來,并一一解釋,以便后查;

          java啟動參數共分為三類;
          其一是標準參數(-),所有的JVM實現都必須實現這些參數的功能,而且向后兼容;
          其二是非標準參數(-X),默認jvm實現這些參數的功能,但是并不保證所有jvm實現都滿足,且不保證向后兼容;
          其三是非Stable參數(-XX),此類參數各個jvm實現會有所不同,將來可能會隨時取消,需要慎重使用;
          本文主要描述標準參數部分,剩下的兩個部分將會陸續推出;

          標準參數列表如下:
          -client 
           設置jvm使用client模式,特點是啟動速度比較快,但運行時性能和內存管理效率不高,通常用于客戶端應用程序或者PC應用開發和調試。

          -server
           設置jvm使server模式,特點是啟動速度比較慢,但運行時性能和內存管理效率很高,適用于生產環境。在具有64位能力的jdk環境下將默認啟用該模式,而忽略-client參數。

          -agentlib:libname[=options] 
           用于裝載本地lib包;
           其中libname為本地代理庫文件名,默認搜索路徑為環境變量PATH中的路徑,options為傳給本地庫啟動時的參數,多個參數之間用逗號分隔。在Windows平臺上jvm搜索本地庫名為libname.dll的文件,在linux上jvm搜索本地庫名為libname.so的文件,搜索路徑環境變量在不同系統上有所不同,比如Solaries上就默認搜索LD_LIBRARY_PATH。
           比如:-agentlib:hprof
           用來獲取jvm的運行情況,包括CPU、內存、線程等的運行數據,并可輸出到指定文件中;windows中搜索路徑為JRE_HOME/bin/hprof.dll。

          -agentpath:pathname[=options] 
           按全路徑裝載本地庫,不再搜索PATH中的路徑;其他功能和agentlib相同;更多的信息待續,在后續的JVMTI部分會詳述。

          -classpath classpath 
          -cp classpath
           
           告知jvm搜索目錄名、jar文檔名、zip文檔名,之間用分號;分隔;使用-classpath后jvm將不再使用CLASSPATH中的類搜索路徑,如果-classpath和CLASSPATH都沒有設置,則jvm使用當前路徑(.)作為類搜索路徑。
           jvm搜索類的方式和順序為:Bootstrap,Extension,User。
           Bootstrap中的路徑是jvm自帶的jar或zip文件,jvm首先搜索這些包文件,用System.getProperty("sun.boot.class.path")可得到搜索路徑。
           Extension是位于JRE_HOME/lib/ext目錄下的jar文件,jvm在搜索完Bootstrap后就搜索該目錄下的jar文件,用System.getProperty("java.ext.dirs")可得到搜索路徑。
           User搜索順序為當前路徑.、CLASSPATH、-classpath,jvm最后搜索這些目錄,用System.getProperty("java.class.path")可得到搜索路徑。

          -Dproperty=value
           設置系統屬性名/值對,運行在此jvm之上的應用程序可用System.getProperty("property")得到value的值。
           如果value中有空格,則需要用雙引號將該值括起來,如-Dname="space string"。
           該參數通常用于設置系統級全局變量值,如配置文件路徑,以便該屬性在程序中任何地方都可訪問。

          -enableassertions[:<package name>"..." | :<class name> ] 
          -ea[:<package name>"..." | :<class name> ]
           
           上述參數就用來設置jvm是否啟動斷言機制(從JDK 1.4開始支持),缺省時jvm關閉斷言機制。
           用-ea 可打開斷言機制,不加<packagename>和classname時運行所有包和類中的斷言,如果希望只運行某些包或類中的斷言,可將包名或類名加到-ea之后。例如要啟動包com.wombat.fruitbat中的斷言,可用命令java -ea:com.wombat.fruitbat...<Main Class>。

          -disableassertions[:<package name>"..." | :<class ; ] 
          -da[:<package name>"..." | :<class name> ]

           用來設置jvm關閉斷言處理,packagename和classname的使用方法和-ea相同,jvm默認就是關閉狀態。
           該參數一般用于相同package內某些class不需要斷言的場景,比如com.wombat.fruitbat需要斷言,但是com.wombat.fruitbat.Brickbat該類不需要,則可以如下運行:
           java -ea:com.wombat.fruitbat...-da:com.wombat.fruitbat.Brickbat <Main Class>。
           
          -enablesystemassertions 
          -esa
           
           激活系統類的斷言。
           
          -disablesystemassertions 
          -dsa
           
           關閉系統類的斷言。

          -jar 
           指定以jar包的形式執行一個應用程序。
           要這樣執行一個應用程序,必須讓jar包的manifest文件中聲明初始加載的Main-class,當然那Main-class必須有public static void main(String[] args)方法。

          -javaagent:jarpath[=options] 
           指定jvm啟動時裝入java語言設備代理。
           Jarpath文件中的mainfest文件必須有Agent-Class屬性。代理類也必須實現公共的靜態public static void premain(String agentArgs, Instrumentation inst)方法(和main方法類似)。當jvm初始化時,將按代理類的說明順序調用premain方法;具體參見java.lang.instrument軟件包的描述。

          -verbose 
          -verbose:class
           
           輸出jvm載入類的相關信息,當jvm報告說找不到類或者類沖突時可此進行診斷。
          -verbose:gc 
           輸出每次GC的相關情況。
          -verbose:jni 
           輸出native方法調用的相關情況,一般用于診斷jni調用錯誤信息。
           
          -version 
           輸出java的版本信息,比如jdk版本、vendor、model。
          -version:release 
           指定class或者jar運行時需要的jdk版本信息;若指定版本未找到,則以能找到的系統默認jdk版本執行;一般情況下,對于jar文件,可以在manifest文件中指定需要的版本信息,而不是在命令行。
           release中可以指定單個版本,也可以指定一個列表,中間用空格隔開,且支持復雜組合,比如:
           -version:"1.5.0_04 1.5*&1.5.1_02+"
           指定class或者jar需要jdk版本為1.5.0_04或者是1.5系列中比1.5.1_02更高的所有版本。

          -showversion 
           輸出java版本信息(與-version相同)之后,繼續輸出java的標準參數列表及其描述。
           
          -? 
          -help
           
           輸出java標準參數列表及其描述。

          -X 
           輸出非標準的參數列表及其描述。

          以上的這些參數我們經常會在很多情況下用到多個的組合,比如我們在用JProfiler進行跟蹤監控時,需要在被監控java啟動參數中加上如下配置:
          -agentlib:jprofilerti=port=8849  -Xbootclasspath/a:/usr/local/jprofiler5/bin/agent.jar
          其中就用到兩個-agentlib和-X參數,bootclasspath參數的詳細信息將會在非標準參數中詳細說明。

          轉自:http://blog.csdn.net/sfdev/article/details/2062042

          這篇文章補充說明了-X、-XX參數的說明:Java命令行運行參數說明大全(偷來的)

          posted @ 2011-12-08 15:49 iLinux 閱讀(5150) | 評論 (0)編輯 收藏

               摘要: 作者:北南南北贊助: eTony,pandonny,懶貓, Arch來自:LinuxSir.Org摘要: 超級用戶是系統最高權限的擁有者,是系統管理唯一的勝任者;由于權限的超級并且達到無所不能的地步,如果管理不擅,必會對系統安全造成威脅。 除了盡可能的避免用直接用超級用戶root登錄系統外,我們還要學會在普通用戶下臨時切換到超級用戶root下完成必要的系統管理工作;從用戶管理和...  閱讀全文
          posted @ 2011-12-08 15:36 iLinux 閱讀(1514) | 評論 (0)編輯 收藏

          hibernate中,比如B類繼承了A類,它們是可以對應同一張表的。
          可以參考如下文章Hibernate繼承映射一:每個類分層結構一張表

          posted @ 2011-12-08 12:50 iLinux 閱讀(139) | 評論 (0)編輯 收藏

          1 web容器啟動,初始化ActionServlet,加載struts-config.xml,根據請求路徑和信息找到ActionBean與FormBean

          2 確定將要調用的ActionBean與FormBean,將請求中包含的值填充到FormBean中(Action中要準備好ActionMapping的參數)

          3 struts將請求分發到相應的的ActionBean處理,ActionMapping參數ActionForm參數request,resposne都做為參數傳給處理請求的ActionBean的execute方法

          4 Action調用業務邏輯方法,得到返回值ActionForward對象

          5 控制控重回ActionServlet,根據Action返回的ActionForward對象,轉發到相應的頁面

          6 處理結果返回瀏覽器

          posted @ 2011-12-08 12:29 iLinux 閱讀(114) | 評論 (0)編輯 收藏

          UML類圖中的關聯、聚合、組合

          posted @ 2011-12-08 12:25 iLinux 閱讀(131) | 評論 (0)編輯 收藏

          nio:  http://jiayanjujyj.iteye.com/blog/1044364



          posted @ 2011-12-08 00:14 iLinux 閱讀(818) | 評論 (0)編輯 收藏

          1 小白長得很像他的哥哥,打一句成語

          答案:真相大白
          Q:老板,你這不叫牛肉面嗎?怎么連牛肉都沒有?!  

          A:人家還叫老婆餅呢,難不成你買的時候還送你一個老婆 ?! 
          Q一根手指頭的英文叫做 ONE,兩根手指頭的英文叫做TWO,依次類推,四根手手指頭的英文叫做 four,那么彎起來的四根手指頭的英文叫什么  

          A答案:WONDERFFUL (彎的 FOUR)  
          Q:一只兔子和一只跑得很快的烏龜賽跑,猜一猜誰贏拉?  

          A:兔子 ~~

          Q:錯~!是烏龜拉,前面有說是一只跑很快的烏龜,跑很快噢~~

          Q:兔子不甘心,又和一只戴了墨鏡的烏龜比賽跑步,這次誰贏拉?  

          A:恩。。兔子吧

          Q:錯~~!那只烏龜把墨鏡一摘,也!又是剛才那只跑很快的烏龜噢

          english version: http://translate.google.com/translate?langpair=zh-CN%7Cen&hl=zh-CN&ie=UTF8&u=http%3A//www.aygfsteel.com/iLinux/archive/2011/12/07/322634.html
          posted @ 2011-12-07 23:31 iLinux 閱讀(148) | 評論 (0)編輯 收藏

          括號為是否線程安全
          list: LinkedList(no) ArrayList(no) Vector(yes) Stack(yes)
          map: HashMap(no) LinkedHashMap(no) HashTable(yes) WeakHashMap TreeMap
          set: HashSet(no) LinkedHashSet(no) SortedSet TreeSet
          最常用的好像為每行的前兩個
          特征:
          1. Linked開頭的適合快速插入,刪除元素, linked維護元素插入的次序
          2. Set 在 HashMap 的基礎上實現, 所以Set結尾的key是不會重復的
          3. Tree開頭的是每次改變發生排序的, 速度慢
          適用:
          1. 需要快速插入,刪除元素, 用 LinkedList; 需要快速隨機訪問元素,用 ArrayList
          2. Vector 類似 ArrayList, 但是是同步的
          3. Stack 繼承 Vector , 是后進先出的堆棧
          4. HashMap, put進去的對象位置會發生變化, LinkedHashMap 則不會
          5. HashSet 是專門為快速查詢而設計的, 插入會產生排序(LinkedHashSet 不會), 存入HashSet的對象必須定義hashCode方法
             我的補充:關于“存入HashSet的對象必須定義hashCode方法”,其實不是必須的,但是,當我們沒有重寫hashCode()時,則所有我們添加進Set的對象都不會有重復現象,我們可以添加多個具有相等值得對象,但是,這就與我們的初衷有了背離,Set本身用于存儲unique的對象,所以我們重寫hashCode()和equals(),符合我們的業務邏輯。
          6. SortedSet 是保持元素的有序順序的Set接口, 添加到 SortedSet 實現類的元素必須實現Comparable接口, TreeSet 類是它的唯一一份實現
          其它:
          1. 非同步的可以進行外部同步,或者使用Collections.synchronizedMap()的方法包裝成一個thread-safe的Map/Set
          2. LinkedHashMap支持兩種排序:插入順序、訪問順序。前者是指按照插入時的順序排序,后者是指按照最舊使用到最近使用的順序
          3. 既然 Set 在 HashMap 的基礎上實現, 那么 HashMap 和 HashSet 有什么區別嗎?
          答: HashMap提供get和put方法, 允許null 值和null 鍵; HashSet 提供add、remove、contains和size方法, 允許null 元素; 其它未知

          轉自:http://xu20cn.blog.51cto.com/274020/229009/
          posted @ 2011-12-07 17:02 iLinux 閱讀(892) | 評論 (0)編輯 收藏

          一、事務的4個基本特征 
              當事務處理系統創建事務時,將確保事務有某些特性。組件的開發者們假設事務的特性應該是一些不需要他們親自管理的特性。這些特性稱為ACID特性。 ACID就是:原子性(Atomicity )、一致性( Consistency )、隔離性或獨立性( Isolation)和持久性(Durabilily)。 
          1、原子性 (Atomicity ) 
              原子性屬性用于標識事務是否完全地完成,一個事務的任何更新要在系統上完全完成,如果由于某種原因出錯,事務不能完成它的全部任務,系統將返回到事務開始前的狀態。 
          讓我們再看一下銀行轉帳的例子。如果在轉帳的過程中出現錯誤,整個事務將會回滾。只有當事務中的所有部分都成功執行了,才將事務寫入磁盤并使變化 永久化。為了提供回滾或者撤消未提交的變化的能力,許多數據源采用日志機制。例如,SQL Server使用一個預寫事務日志,在將數據應用于(或提交到)實際數據頁面前,先寫在事務日志上。但是,其他一些數據源不是關系型數據庫管理系統 (RDBMS),它們管理未提交事務的方式完全不同。只要事務回滾時,數據源可以撤消所有未提交的改變,那么這種技術應該可用于管理事務。 
          2、一致性( Consistency ) 
              事務在系統完整性中實施一致性,這通過保證系統的任何事務最后都處于有效狀態來實現。如果事務成功地完成,那么系統中所有變化將正確地應用,系統處于有效狀態。如果在事務中出現錯誤,那么系統中的所有變化將自動地回滾,系統返回到原始狀態。因為事務開 
          始時系統處于一致狀態,所以現在系統仍然處于一致狀態。 再讓我們回頭看一下銀行轉帳的例子,在帳戶轉換和資金轉移前,帳戶處于有效狀態。如果事務成功地完成,并且提交事務,則帳戶處于新的有效的狀態。如果事務出錯,終止后,帳戶返回到原先的有效狀態。 
          記住,事務不負責實施數據完整性,而僅僅負責在事務提交或終止以后確保數據返回到一致狀態。理解數據完整性規則并寫代碼實現完整性的重任通常落在 開發者肩上,他們根據業務要求進行設計。 當許多用戶同時使用和修改同樣的數據時,事務必須保持其數據的完整性和一致性。因此我們進一步研究A C I D特性中的下一個特性:隔離性。 
          3、隔離性 ( Isolation) 
              在隔離狀態執行事務,使它們好像是系統在給定時間內執行的唯一操作。如果有兩個事務,運行在相同的時間內,執行相同的功能,事務的隔離性將確保每一事務在 系統中認為只有該事務在使用系統。 這種屬性有時稱為串行化,為了防止事務操作間的混淆,必須串行化或序列化請求,使得在同一時間僅有一個請求用于同一數據。重要的是,在隔離狀態執行事務, 系統的狀態有可能是不一致的,在結束事務前,應確保系統處于一致狀態。但是在每個單獨的事務中,系統的狀態可能會發生變化。如果事務不是在隔離狀態運行, 它就可能從系統中訪問數據,而系統可能處于不一致狀態。通過提供事務隔離,可以阻止這類事件的發生。在銀行的示例中,這意味著在這個系統內,其他過程和事 務在我們的事務完成前看不到我們的事務引起的任何變化,這對于終止的情況非常重要。如果有另一個過程根據帳戶余額進行相應處理,而它在我們的事務完成前就 能看到它造成的變化,那么這個過程的決策可能 
          建立在錯誤的數據之上,因為我們的事務可能終止。這就是說明了為什么事務產生的變化,直到事務完成,才對系統的其他部分可見。隔離性不僅僅保 證多個事務不能同時修改相同數據,而且能夠保證事務操作產生的變化直到變化被提交或終止時才能對另一個事務可見,并發的事務彼此之間毫無影響。這就意味著 所有要求修改或讀取的數據已經被鎖定在事務中,直到事務完成才能釋放。大多數數據庫,例如SQL Server以及其他的RDBMS,通過使用鎖定來實現隔離,事務中涉及的各個數據項或數據集使用鎖定來防止并發訪問。 
          4、持久性 (Durabilily) 
              持久性意味著一旦事務執行成功,在系統中產生的所有變化將是永久的。應該存在一些檢查點防止在系統失敗時丟失信息。甚至硬件本身失敗,系統的狀態仍能通過在日志中記錄事務完成的任務進行重建。持久性的概念允許開發者認為不管系統以后發生了什么變化,完 
          成的事務是系統永久的部分。 在銀行的例子中,資金的轉移是永久的,一直保持在系統中。這聽起來似乎簡單,但這,依賴于將數據寫入磁盤,特別需要指出的是,在事務完全完成并提交后才寫 入磁盤的。 所有這些事務特性,不管其內部如何關聯,僅僅是保證從事務開始到事務完成,不管事務成功與否,都能正確地管理事務涉及的數據 ,當事務處理系統創建事務 時,將確保事務有某些特性。組件的開發者們假設事務的特性應該是一些不需要他們親自管理的特性。 
          二、為什么需要對事務并發控制 
              如果不對事務進行并發控制,我們看看數據庫并發操作是會有那些異常情形 
          1、丟失更新(Lost update) 
              兩個事務都同時更新一行數據,但是第二個事務卻中途失敗退出,導致對數據的兩個修改都失效了。 
          2、臟讀(Dirty Reads) 
              一個事務開始讀取了某行數據,但是另外一個事務已經更新了此數據但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被回滾。 
          3、非重復讀(Non-repeatable Reads) 
             一個事務對同一行數據重復讀取兩次,但是卻得到了不同的結果。同一查詢在同一事務中多次進行,由于其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生非重復讀。 
          4、二類丟失更新(Second lost updates problem) 
              無法重復讀取的特例。有兩個并發事務同時讀取同一行數據,然后其中一個對它進行修改提交,而另一個也進行了修改提交。這就會造成第一次寫操作失效。 
          5、幻像讀(Phantom Reads) 
              事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查 
          詢中未出現的數據(這里并不要求兩次查詢的SQL語句相同)。這是因為在兩次查詢過程中有另外一個事務插入數據造成的。 
          三、數據庫的隔離級別 
             為了兼顧并發效率和異常控制,在標準SQL規范中,定義了4個事務隔離級別,(ORACLE和SQLSERER對標準隔離級別有不同的實現 ) 
          1、未提交讀(Read Uncommitted) 
              直譯就是"讀未提交",意思就是即使一個更新語句沒有提交,但是別 
          的事務可以讀到這個改變.這是很不安全的。允許任務讀取數據庫中未提交的數據更改,也稱為臟讀。 
          2、提交讀(Read Committed) 
             直譯就是"讀提交",可防止臟讀,意思就是語句提交以后即執行了COMMIT以后 
          別的事務就能讀到這個改變. 只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 
          3、可重復讀(Repeatable Read): 
             直譯就是"可以重復讀",這是說在同一個事務里面先后執行同一個查詢語句的時候,得到的結果是一樣的.在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重復讀,但是還存在幻象讀 
          4、串行讀(Serializable) 
             直譯就是"序列化",意思是說這個事務執行的時候不允許別的事務并發執行. 完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

           

          四,隔離級別對并發的控制 
          下表是各隔離級別對各種異常的控制能力。


          LU丟失更新DR臟讀NRR非重復讀SLU二類丟失更新PR幻像讀
          未提交讀 RUYYYYY
          提交讀 RCNNYYY
          可重復讀 RRNNNNY
          串行讀 SNNNNN

           

           

          順便舉一小例。

          MS_SQL: 
          --事務一 
          set transaction isolation level serializable 
          begin tran 
          insert into test values('xxx') 
          --事務二 
          set transaction isolation level read committed 
          begin tran 
          select * from test 
          --事務三 
          set transaction isolation level read uncommitted 
          begin tran 
          select * from test 
          在查詢分析器中執行事務一后,分別執行事務二,和三。結果是事務二會等待,而事務三則會執行。

          ORACLE: 
          --事務一 
          set transaction isolation level serializable; 
          insert into test values('xxx'); 
          select * from test; 
          --事務二 
          set transaction isolation level read committed--ORACLE默認級別 
          select * from test 
          執行事務一后,執行事務二。結果是事務二只讀出原有的數據,無視事務一的插入操作。

          MYSQL 
          查看InnoDB系統級別的事務隔離級別: 
          以下為引用的內容: 
          mysql> SELECT @@global.tx_isolation; 
          +-----------------------+ 
          | @@global.tx_isolation | 
          +-----------------------+ 
          | REPEATABLE-READ   | 
          +-----------------------+ 
          1 row in set (0.00 sec) 
          查看InnoDB會話級別的事務隔離級別: 
          以下為引用的內容: 
          mysql> SELECT @@tx_isolation; 
          +-----------------+ 
          | @@tx_isolation | 
          +-----------------+ 
          | REPEATABLE-READ | 
          +-----------------+ 
          1 row in set (0.00 sec) 
          修改事務隔離級別: 
          以下為引用的內容: 
            mysql> set global transaction isolation level read committed; 
            Query OK, 0 rows affected (0.00 sec) 
            mysql> set session transaction isolation level read committed; 
            Query OK, 0 rows affected (0.00 sec) 
          InnoDB的可重復讀隔離級別和其他數據庫的可重復讀是有區別的,不會造成幻象讀(phantom read),所謂幻象讀,就是同一個事務內,多次select,可以讀取到其他session insert并已經commit的數據。下面是一個小的測試,證明InnoDB的可重復讀隔離級別不會造成幻象讀。測試涉及兩個session,分別為 session 1和session 2,隔離級別都是repeateable read,關閉autocommit 
          以下為引用的內容: 
          mysql> select @@tx_isolation; 
          +-----------------+ 
          | @@tx_isolation | 
          +-----------------+ 
          | REPEATABLE-READ | 
          +-----------------+ 
          1 row in set (0.00 sec) 
            mysql> set autocommit=off; 
            Query OK, 0 rows affected (0.00 sec) 
            session 1 創建表并插入測試數據 
            mysql> create table test(i int) engine=innodb; 
            Query OK, 0 rows affected (0.00 sec)

            mysql> insert into test values(1); 
            Query OK, 1 row affected (0.00 sec) 
            session 2 查詢,沒有數據,正常,session1沒有提交,不允許臟讀 
            mysql> select * from test; 
            Empty set (0.00 sec) 
            session 1 提交事務 
            mysql> commit; 
            Query OK, 0 rows affected (0.00 sec) 
            session 2 查詢,還是沒有數據,沒有產生幻象讀 
            mysql> select * from test; 
            Empty set (0.00 sec) 
          以上試驗版本: 
          mysql> select version(); 
          +-------------------------+ 
          | version()       | 
          +-------------------------+ 
          | 5.0.37-community-nt-log | 
          +-------------------------+ 
          1 row in set (0.00 sec)

          五、并發一致性問題的解決辦法 
          1 封鎖(Locking) 
              封鎖是實現并發控制的一個非常重要的技術。所謂封鎖就是事務T在對某個數據對象例如表、記錄等操作之前,先向系統發出請求,對其加鎖。加鎖后事務T就對該 數據對象有了一定的控制,在事務T釋放它的鎖之前,其它的事務不能更新此數據對象。 基本的封鎖類型有兩種:排它鎖(Exclusive locks 簡記為X鎖)和共享鎖(Share locks 簡記為S鎖)。 
              排它鎖又稱為寫鎖。若事務T對數據對象A加上X鎖,則只允許T讀取和修改A,其它任何事務都不能再對A加任何類型的鎖,直到T釋放A上的鎖。這就保證了其它事務在T釋放A上的鎖之前不能再讀取和修改A。 
              共享鎖又稱為讀鎖。若事務T對數據對象A加上S鎖,則其它事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這就保證了其它事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。 
          2 封鎖協議 
              在 運用X鎖和S鎖這兩種基本封鎖,對數據對象加鎖時,還需要約定一些規則,例如應何時申請X鎖或S鎖、持鎖時間、何時釋放等。我們稱這些規則為封鎖協議 (Locking Protocol)。對封鎖方式規定不同的規則,就形成了各種不同的封鎖協議。下面介紹三級封鎖協議。三級封鎖協議分別在不同程度上解決了丟失的修改、不 可重復讀和讀"臟"數據等不一致性問題,為并發操作的正確調度提供一定的保證。下面只給出三級封鎖協議的定義,不再做過多探討。 
              1 級封鎖協議是:事務T在修改數據R之前必須先對其加X鎖,直到事務結束才釋放。事務結束包括正常結束(COMMIT)和非正常結束(ROLLBACK)。 1級封鎖協議可防止丟失修改,并保證事務T是可恢復的。在1級封鎖協議中,如果僅僅是讀數據不對其進行修改,是不需要加鎖的,所以它不能保證可重復讀和不 讀"臟"數據。 
              2級封鎖協議是:1級封鎖協議加上事務T在讀取數據R之前必須先對其加S鎖,讀完后即可釋放S鎖。2級封鎖協議除防止了丟失修改,還可進一步防止讀"臟"數據。 
              3級封鎖協議是:1級封鎖協議加上事務T在讀取數據R之前必須先對其加S鎖,直到事務結束才釋放。3級封鎖協議除防止了丟失修改和不讀'臟'數據外,還進一步防止了不可重復讀。 
          六、一般處理并發問題時的步驟: 
          1、開啟事務。 
          2、申請寫權限,也就是給對象(表或記錄)加鎖。 
          3、假如失敗,則結束事務,過一會重試。 
          4、假如成功,也就是給對象加鎖成功,防止其他用戶再用同樣的方式打開。 
          5、進行編輯操作。 
          6、寫入所進行的編輯結果。 
          7、假如寫入成功,則提交事務,完成操作。 
          8、假如寫入失敗,則回滾事務,取消提交。 
          9、(7.8)兩步操作已釋放了鎖定的對象,恢復到操作前的狀態。

          轉自:http://www.cnblogs.com/tqsummer/archive/2010/07/11/1775209.html

          posted @ 2011-12-07 14:11 iLinux 閱讀(569) | 評論 (0)編輯 收藏

          僅列出標題
          共3頁: 上一頁 1 2 3 下一頁 
          主站蜘蛛池模板: 双峰县| 彭阳县| 河东区| 高雄县| 黄冈市| 汶上县| 咸阳市| 鱼台县| 徐水县| 丹巴县| 鄄城县| 万州区| 重庆市| 宁蒗| 五大连池市| 浦城县| 永济市| 平湖市| 喀喇沁旗| 尖扎县| 商南县| 米林县| 正安县| 高要市| 宜春市| 武义县| 南宫市| 永兴县| 建始县| 杭锦后旗| 花莲县| 共和县| 吉林省| 邯郸市| 罗江县| 岳普湖县| 南召县| 赤城县| 凤城市| 祁门县| 宝鸡市|