隨筆 - 4, 文章 - 0, 評論 - 0, 引用 - 0
          數據加載中……

          2008年10月16日

          關于數據庫的優化

          數據庫的優化方案
          本文首先討論了基于第三范式的數據庫表的基本設計,著重論述了建立主鍵和索引的策略和方案,然后從數據庫表的擴展設計和庫表對象的放置等角度概述了數據庫管理系統的優化方案。
          關鍵詞: 優化(Optimizing) 第三范式(3NF) 冗余數據(Redundant Data) 索引(Index) 數據分割(Data Partitioning) 對象放置(Object Placement)
          1 引言
          數據庫優化的目標無非是避免磁盤I/O瓶頸、減少CPU利用率和減少資源競爭。為了便于讀者閱讀和理解,筆者參閱了Sybase、Informix和Oracle等大型數據庫系統參考資料,基于多年的工程實踐經驗,從基本表設計、擴展設計和數據庫表對象放置等角度進行討論,著重討論了如何避免磁盤I/O瓶頸和減少資源競爭,相信讀者會一目了然。
          2 基于第三范式的基本表設計
          在基于表驅動的信息管理系統(MIS)中,基本表的設計規范是第三范式(3NF)。第三范式的基本特征是非主鍵屬性只依賴于主鍵屬性。基于第三范式的數據庫表設計具有很多優點:一是消除了冗余數據,節省了磁盤存儲空間;二是有良好的數據完整性限制,即基于主外鍵的參照完整限制和基于主鍵的實體完整性限制,這使得數據容易維護,也容易移植和更新;三是數據的可逆性好,在做連接(Join)查詢或者合并表時不遺漏、也不重復;四是因消除了冗余數據(冗余列),在查詢(Select)時每個數據頁存的數據行就多,這樣就有效地減少了邏輯I/O,每個Cash存的頁面就多,也減少物理I/O;五是對大多數事務(Transaction)而言,運行性能好;六是物理設計(Physical Design)的機動性較大,能滿足日益增長的用戶需求。
          在基本表設計中,表的主鍵、外鍵、索引設計占有非常重要的地位,但系統設計人員往往只注重于滿足用戶要求,而沒有從系統優化的高度來認識和重視它們。實際上,它們與系統的運行性能密切相關。現在從系統數據庫優化角度討論這些基本概念及其重要意義:
          (1)主鍵(Primary Key):主鍵被用于復雜的SQL語句時,頻繁地在數據訪問中被用到。一個表只有一個主鍵。主鍵應該有固定值(不能為Null或缺省值,要有相對穩定性),不含代碼信息,易訪問。把常用(眾所周知)的列作為主鍵才有意義。短主鍵最佳(小于25bytes),主鍵的長短影響索引的大小,索引的大小影響索引頁的大小,從而影響磁盤I/O。主鍵分為自然主鍵和人為主鍵。自然主鍵由實體的屬性構成,自然主鍵可以是復合性的,在形成復合主鍵時,主鍵列不能太多,復合主鍵使得Join*作復雜化、也增加了外鍵表的大小。人為主鍵是,在沒有合適的自然屬性鍵、或自然屬性復雜或靈敏度高時,人為形成的。人為主鍵一般是整型值(滿足最小化要求),沒有實際意義,也略微增加了表的大小;但減少了把它作為外鍵的表的大小。
          (2)外鍵(Foreign Key):外鍵的作用是建立關系型數據庫中表之間的關系(參照完整性),主鍵只能從獨立的實體遷移到非獨立的實體,成為后者的一個屬性,被稱為外鍵。
          (3)索引(Index):利用索引優化系統性能是顯而易見的,對所有常用于查詢中的Where子句的列和所有用于排序的列創建索引,可以避免整表掃描或訪問,在不改變表的物理結構的情況下,直接訪問特定的數據列,這樣減少數據存取時間;利用索引可以優化或排除耗時的分類*作;把數據分散到不同的頁面上,就分散了插入的數據;主鍵自動建立了唯一索引,因此唯一索引也能確保數據的唯一性(即實體完整性);索引碼越小,定位就越直接;新建的索引效能最好,因此定期更新索引非常必要。索引也有代價:有空間開銷,建立它也要花費時間,在進行Insert、Delete和Update*作時,也有維護代價。索引有兩種:聚族索引和非聚族索引。一個表只能有一個聚族索引,可有多個非聚族索引。使用聚族索引查詢數據要比使用非聚族索引快。在建索引前,應利用數據庫系統函數估算索引的大小。
          ① 聚族索引(Clustered Index):聚族索引的數據頁按物理有序儲存,占用空間小。選擇策略是,被用于Where子句的列:包括范圍查詢、模糊查詢或高度重復的列(連續磁盤掃描);被用于連接Join*作的列;被用于Order by和Group by子句的列。聚族索引不利于插入*作,另外沒有必要用主鍵建聚族索引。
          ② 非聚族索引(Nonclustered Index):與聚族索引相比,占用空間大,而且效率低。選擇策略是,被用于Where子句的列:包括范圍查詢、模糊查詢(在沒有聚族索引時)、主鍵或外鍵列、點(指針類)或小范圍(返回的結果域小于整表數據的20%)查詢;被用于連接Join*作的列、主鍵列(范圍查詢);被用于Order by和Group by子句的列;需要被覆蓋的列。對只讀表建多個非聚族索引有利。索引也有其弊端,一是創建索引要耗費時間,二是索引要占有大量磁盤空間,三是增加了維護代價(在修改帶索引的數據列時索引會減緩修改速度)。那么,在哪種情況下不建索引呢?對于小表(數據小于5頁)、小到中表(不直接訪問單行數據或結果集不用排序)、單值域(返回值密集)、索引列值太長(大于20bitys)、容易變化的列、高度重復的列、Null值列,對沒有被用于Where子語句和Join查詢的列都不能建索引。另外,對主要用于數據錄入的,盡可能少建索引。當然,也要防止建立無效索引,當Where語句中多于5個條件時,維護索引的開銷大于索引的效益,這時,建立臨時表存儲有關數據更有效。
          批量導入數據時的注意事項:在實際應用中,大批量的計算(如電信話單計費)用C語言程序做,這種基于主外鍵關系數據計算而得的批量數據(文本文件),可利用系統的自身功能函數(如Sybase的BCP命令)快速批量導入,在導入數據庫表時,可先刪除相應庫表的索引,這有利于加快導入速度,減少導入時間。在導入后再重建索引以便優化查詢。
          (4)鎖:鎖是并行處理的重要機制,能保持數據并發的一致性,即按事務進行處理;系統利用鎖,保證數據完整性。因此,我們避免不了死鎖,但在設計時可以充分考慮如何避免長事務,減少排它鎖時間,減少在事務中與用戶的交互,杜絕讓用戶控制事務的長短;要避免批量數據同時執行,尤其是耗時并用到相同的數據表。鎖的征用:一個表同時只能有一個排它鎖,一個用戶用時,其它用戶在等待。若用戶數增加,則Server的性能下降,出現“假死”現象。如何避免死鎖呢?從頁級鎖到行級鎖,減少了鎖征用;給小表增加無效記錄,從頁級鎖到行級鎖沒有影響,若在同一頁內競爭有影響,可選擇合適的聚族索引把數據分配到不同的頁面;創建冗余表;保持事務簡短;同一批處理應該沒有網絡交互。
          (5)查詢優化規則:在訪問數據庫表的數據(Access Data)時,要盡可能避免排序(Sort)、連接(Join)和相關子查詢*作。經驗告訴我們,在優化查詢時,必須做到:
          ① 盡可能少的行;
          ② 避免排序或為盡可能少的行排序,若要做大量數據排序,最好將相關數據放在臨時表中*作;用簡單的鍵(列)排序,如整型或短字符串排序;
          ③ 避免表內的相關子查詢;
          ④ 避免在Where子句中使用復雜的表達式或非起始的子字符串、用長字符串連接;
          ⑤ 在Where子句中多使用“與”(And)連接,少使用“或”(Or)連接;
          ⑥ 利用臨時數據庫。在查詢多表、有多個連接、查詢復雜、數據要過濾時,可以建臨時表(索引)以減少I/O。但缺點是增加了空間開銷。
          除非每個列都有索引支持,否則在有連接的查詢時分別找出兩個動態索引,放在工作表中重新排序。
          3 基本表擴展設計
          基于第三范式設計的庫表雖然有其優越性(見本文第一部分),然而在實際應用中有時不利于系統運行性能的優化:如需要部分數據時而要掃描整表,許多過程同時競爭同一數據,反復用相同行計算相同的結果,過程從多表獲取數據時引發大量的連接*作,當數據來源于多表時的連接*作;這都消耗了磁盤I/O和CPU時間。
          尤其在遇到下列情形時,我們要對基本表進行擴展設計:許多過程要頻繁訪問一個表、子集數據訪問、重復計算和冗余數據,有時用戶要求一些過程優先或低的響應時間。
          如何避免這些不利因素呢?根據訪問的頻繁程度對相關表進行分割處理、存儲冗余數據、存儲衍生列、合并相關表處理,這些都是克服這些不利因素和優化系統運行的有效途徑。
          3.1 分割表或儲存冗余數據
          分割表分為水平分割表和垂直分割表兩種。分割表增加了維護數據完整性的代價。
          水平分割表:一種是當多個過程頻繁訪問數據表的不同行時,水平分割表,并消除新表中的冗余數據列;若個別過程要訪問整個數據,則要用連接*作,這也無妨分割表;典型案例是電信話單按月分割存放。另一種是當主要過程要重復訪問部分行時,最好將被重復訪問的這些行單獨形成子集表(冗余儲存),這在不考慮磁盤空間開銷時顯得十分重要;但在分割表以后,增加了維護難度,要用觸發器立即更新、或存儲過程或應用代碼批量更新,這也會增加額外的磁盤I/O開銷。
          垂直分割表(不破壞第三范式),一種是當多個過程頻繁訪問表的不同列時,可將表垂直分成幾個表,減少磁盤I/O(每行的數據列少,每頁存的數據行就多,相應占用的頁就少),更新時不必考慮鎖,沒有冗余數據。缺點是要在插入或刪除數據時要考慮數據的完整性,用存儲過程維護。另一種是當主要過程反復訪問部分列時,最好將這部分被頻繁訪問的列數據單獨存為一個子集表(冗余儲存),這在不考慮磁盤空間開銷時顯得十分重要;但這增加了重疊列的維護難度,要用觸發器立即更新、或存儲過程或應用代碼批量更新,這也會增加額外的磁盤I/O開銷。垂直分割表可以達到最大化利用Cache的目的。
          總之,為主要過程分割表的方法適用于:各個過程需要表的不聯結的子集,各個過程需要表的子集,訪問頻率高的主要過程不需要整表。在主要的、頻繁訪問的主表需要表的子集而其它主要頻繁訪問的過程需要整表時則產生冗余子集表。
          注意,在分割表以后,要考慮重新建立索引。
          3.2 存儲衍生數據
          對一些要做大量重復性計算的過程而言,若重復計算過程得到的結果相同(源列數據穩定,因此計算結果也不變),或計算牽扯多行數據需額外的磁盤I/O開銷,或計算復雜需要大量的CPU時間,就考慮存儲計算結果(冗余儲存)。現予以分類說明:
          若在一行內重復計算,就在表內增加列存儲結果。但若參與計算的列被更新時,必須要用觸發器更新這個新列。
          若對表按類進行重復計算,就增加新表(一般而言,存放類和結果兩列就可以了)存儲相關結果。但若參與計算的列被更新時,就必須要用觸發器立即更新、或存儲過程或應用代碼批量更新這個新表。
          若對多行進行重復性計算(如排名次),就在表內增加列存儲結果。但若參與計算的列被更新時,必須要用觸發器或存儲過程更新這個新列。
          總之,存儲冗余數據有利于加快訪問速度;但違反了第三范式,這會增加維護數據完整性的代價,必須用觸發器立即更新、或存儲過程或應用代碼批量更新,以維護數據的完整性。
          3.3 消除昂貴結合
          對于頻繁同時訪問多表的一些主要過程,考慮在主表內存儲冗余數據,即存儲冗余列或衍生列(它不依賴于主鍵),但破壞了第三范式,也增加了維護難度。在源表的相關列發生變化時,必須要用觸發器或存儲過程更新這個冗余列。當主要過程總同時訪問兩個表時可以合并表,這樣可以減少磁盤I/O*作,但破壞了第三范式,也增加了維護難度。對父子表和1:1關系表合并方法不同:合并父子表后,產生冗余表;合并1:1關系表后,在表內產生冗余數據。
          4 數據庫對象的放置策略
          數據庫對象的放置策略是均勻地把數據分布在系統的磁盤中,平衡I/O訪問,避免I/O瓶頸。
          ⑴ 訪問分散到不同的磁盤,即使用戶數據盡可能跨越多個設備,多個I/O運轉,避免I/O競爭,克服訪問瓶頸;分別放置隨機訪問和連續訪問數據。
          ⑵ 分離系統數據庫I/O和應用數據庫I/O。把系統審計表和臨時庫表放在不忙的磁盤上。
          ⑶ 把事務日志放在單獨的磁盤上,減少磁盤I/O開銷,這還有利于在障礙后恢復,提高了系統的安全性。
          ⑷ 把頻繁訪問的“活性”表放在不同的磁盤上;把頻繁用的表、頻繁做Join*作的表分別放在單獨的磁盤上,甚至把把頻繁訪問的表的字段放在不同的磁盤上,把訪問分散到不同的磁盤上,避免I/O爭奪;
          ⑸ 利用段分離頻繁訪問的表及其索引(非聚族的)、分離文本和圖像數據。段的目的是平衡I/O,避免瓶頸,增加吞吐量,實現并行掃描,提高并發度,最大化磁盤的吞吐量。利用邏輯段功能,分別放置“活性”表及其非聚族索引以平衡I/O。當然最好利用系統的默認段。另外,利用段可以使備份和恢復數據更加靈活,使系統授權更加靈活。 
           

          posted @ 2008-10-21 00:46 java民工 閱讀(274) | 評論 (0)編輯 收藏

          hibernate的緩存機制

          Hibernate緩存機制緩存是介于應用程序和物理數據源之間,其作用是為了降低應用程序對物理數據源訪問的頻次,從而提高了應用的運行性能。緩存內的數據是對物理數據源中的數據的復制,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。
            緩存的介質一般是內存,所以讀寫速度很快。但如果緩存中存放的數據量非常大時,也會用硬盤作為緩存介質。緩存的實現不僅僅要考慮存儲的介質,還要考慮到管理緩存的并發訪問和緩存數據的生命周期。
            Hibernate的緩存包括Session的緩存和SessionFactory的緩存,其中SessionFactory的緩存又可以分為兩類:內置緩存和外置緩存。Session的緩存是內置的,不能被卸載,也被稱為Hibernate的第一級緩存。SessionFactory的內置緩存和Session的緩存在實現方式上比較相似,前者是SessionFactory對象的一些集合屬性包含的數據,后者是指Session的一些集合屬性包含的數據。SessionFactory的內置緩存中存放了映射元數據和預定義SQL語句,映射元數據是映射文件中數據的拷貝,而預定義SQL語句是在Hibernate初始化階段根據映射元數據推導出來,SessionFactory的內置緩存是只讀的,應用程序不能修改緩存中的映射元數據和預定義SQL語句,因此SessionFactory不需要進行內置緩存與映射文件的同步。SessionFactory的外置緩存是一個可配置的插件。在默認情況下,SessionFactory不會啟用這個插件。外置緩存的數據是數據庫數據的拷貝,外置緩存的介質可以是內存或者硬盤。SessionFactory的外置緩存也被稱為Hibernate的第二級緩存。

            Hibernate的這兩級緩存都位于持久化層,存放的都是數據庫數據的拷貝,那么它們之間的區別是什么呢?為了理解二者的區別,需要深入理解持久化層的緩存的兩個特性:緩存的范圍和緩存的并發訪問策略。

          持久化層的緩存的范圍

            緩存的范圍決定了緩存的生命周期以及可以被誰訪問。緩存的范圍分為三類。

            1 事務范圍:緩存只能被當前事務訪問。緩存的生命周期依賴于事務的生命周期,當事務結束時,緩存也就結束生命周期。在此范圍下,緩存的介質是內存。事務可以是數據庫事務或者應用事務,每個事務都有獨自的緩存,緩存內的數據通常采用相互關聯的的對象形式。

            2 進程范圍:緩存被進程內的所有事務共享。這些事務有可能是并發訪問緩存,因此必須對緩存采取必要的事務隔離機制。緩存的生命周期依賴于進程的生命周期,進程結束時,緩存也就結束了生命周期。進程范圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬盤。緩存內的數據既可以是相互關聯的對象形式也可以是對象的松散數據形式。松散的對象數據形式有點類似于對象的序列化數據,但是對象分解為松散的算法比對象序列化的算法要求更快。

            3 集群范圍:在集群環境中,緩存被一個機器或者多個機器的進程共享。緩存中的數據被復制到集群環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致性,緩存中的數據通常采用對象的松散數據形式。

            對大多數應用來說,應該慎重地考慮是否需要使用集群范圍的緩存,因為訪問的速度不一定會比直接訪問數據庫數據的速度快多少。

            持久化層可以提供多種范圍的緩存。如果在事務范圍的緩存中沒有查到相應的數據,還可以到進程范圍或集群范圍的緩存內查詢,如果還是沒有查到,那么只有到數據庫中查詢。事務范圍的緩存是持久化層的第一級緩存,通常它是必需的;進程范圍或集群范圍的緩存是持久化層的第二級緩存,通常是可選的。

          持久化層的緩存的并發訪問策略

            當多個并發的事務同時訪問持久化層的緩存的相同數據時,會引起并發問題,必須采用必要的事務隔離措施。

            在進程范圍或集群范圍的緩存,即第二級緩存,會出現并發問題。因此可以設定以下四種類型的并發訪問策略,每一種策略對應一種事務隔離級別。

            事務型:僅僅在受管理環境中適用。它提供了Repeatable Read事務隔離級別。對于經常被讀但很少修改的數據,可以采用這種隔離類型,因為它可以防止臟讀和不可重復讀這類的并發問題。

            讀寫型:提供了Read Committed事務隔離級別。僅僅在非集群的環境中適用。對于經常被讀但很少修改的數據,可以采用這種隔離類型,因為它可以防止臟讀這類的并發問題。

            非嚴格讀寫型:不保證緩存與數據庫中數據的一致性。如果存在兩個事務同時訪問緩存中相同數據的可能,必須為該數據配置一個很短的數據過期時間,從而盡量避免臟讀。對于極少被修改,并且允許偶爾臟讀的數據,可以采用這種并發訪問策略。

            只讀型:對于從來不會修改的數據,如參考數據,可以使用這種并發訪問策略。

            事務型并發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,并發性能就越低。

          什么樣的數據適合存放到第二級緩存中?

          1 很少被修改的數據

          2 不是很重要的數據,允許出現偶爾并發的數據

          3 不會被并發訪問的數據

          4 參考數據

          不適合存放到第二級緩存的數據?

          1 經常被修改的數據

          2 財務數據,絕對不允許出現并發

          3 與其他應用共享的數據。

          Hibernate的二級緩存

            如前所述,Hibernate提供了兩級緩存,第一級是Session的緩存。由于Session對象的生命周期通常對應一個數據庫事務或者一個應用事務,因此它的緩存是事務范圍的緩存。第一級緩存是必需的,不允許而且事實上也無法比卸除。在第一級緩存中,持久化類的每個實例都具有唯一的OID。

            第二級緩存是一個可插拔的的緩存插件,它是由SessionFactory負責管理。由于SessionFactory對象的生命周期和應用程序的整個過程對應,因此第二級緩存是進程范圍或者集群范圍的緩存。這個緩存中存放的對象的松散數據。第二級對象有可能出現并發問題,因此需要采用適當的并發訪問策略,該策略為被緩存的數據提供了事務隔離級別。緩存適配器用于把具體的緩存實現軟件與Hibernate集成。第二級緩存是可選的,可以在每個類或每個集合的粒度上配置第二級緩存。

          Hibernate的二級緩存策略的一般過程如下:

          1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。

          2) 把獲得的所有數據對象根據ID放入到第二級緩存中。

          3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。

          4) 刪除、更新、增加數據的時候,同時更新緩存。

            Hibernate的二級緩存策略,是針對于ID查詢的緩存策略,對于條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query緩存。

          Hibernate的Query緩存策略的過程如下:

          1) Hibernate首先根據這些信息組成一個Query Key,Query Key包括條件查詢的請求一般信息:SQL, SQL需要的參數,記錄范圍(起始位置rowStart,最大記錄個數maxRows),等。

          2) Hibernate根據這個Query Key到Query緩存中查找對應的結果列表。如果存在,那么返回這個結果列表;如果不存在,查詢數據庫,獲取結果列表,把整個結果列表根據Query Key放入到Query緩存中。

          3) Query Key中的SQL涉及到一些表名,如果這些表的任何數據發生修改、刪除、增加等操作,這些相關的Query Key都要從緩存中清空
           

          posted @ 2008-10-21 00:46 java民工 閱讀(226) | 評論 (0)編輯 收藏

          關于log4j配置文檔詳解

          log4j.properties 使用
          一.參數意義說明
          輸出級別的種類
          ERROR、WARN、INFO、DEBUG
          ERROR 為嚴重錯誤 主要是程序的錯誤
          WARN 為一般警告,比如session丟失
          INFO 為一般要顯示的信息,比如登錄登出
          DEBUG 為程序的調試信息
          配置日志信息輸出目的地
          log4j.appender.appenderName = fully.qualified.name.of.appender.class
          1.org.apache.log4j.ConsoleAppender(控制臺)
          2.org.apache.log4j.FileAppender(文件)
          3.org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件)
          4.org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
          5.org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
          配置日志信息的格式
          log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
          1.org.apache.log4j.HTMLLayout(以HTML表格形式布局),
          2.org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
          3.org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
          4.org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等等信息)
          控制臺選項
          Threshold=DEBUG:指定日志消息的輸出最低層次。
          ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
          Target=System.err:默認情況下是:System.out,指定輸出控制臺
          FileAppender 選項
          Threshold=DEBUF:指定日志消息的輸出最低層次。
          ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
          File=mylog.txt:指定消息輸出到mylog.txt文件。
          Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
          RollingFileAppender 選項
          Threshold=DEBUG:指定日志消息的輸出最低層次。
          ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
          File=mylog.txt:指定消息輸出到mylog.txt文件。
          Append=false:默認值是true,即將消息增加到指定文件中,false指將消息覆蓋指定的文件內容。
          MaxFileSize=100KB: 后綴可以是KB, MB 或者是 GB. 在日志文件到達該大小時,將會自動滾動,即將原來的內容移到mylog.log.1文件。
          MaxBackupIndex=2:指定可以產生的滾動文件的最大數。
          log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
          日志信息格式中幾個符號所代表的含義:
           -X號: X信息輸出時左對齊;
           %p: 輸出日志信息優先級,即DEBUG,INFO,WARN,ERROR,FATAL,
           %d: 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
           %r: 輸出自應用啟動到輸出該log信息耗費的毫秒數
           %c: 輸出日志信息所屬的類目,通常就是所在類的全名
           %t: 輸出產生該日志事件的線程名
           %l: 輸出日志事件的發生位置,相當于%C.%M(%F:%L)的組合,包括類目名、發生的線程,以及在代碼中的行數。舉例:Testlog4.main (TestLog4.java:10)
           %x: 輸出和當前線程相關聯的NDC(嵌套診斷環境),尤其用到像java servlets這樣的多客戶多線程的應用中。
           %%: 輸出一個"%"字符
           %F: 輸出日志消息產生時所在的文件名稱
           %L: 輸出代碼中的行號
           %m: 輸出代碼中指定的消息,產生的日志具體信息
           %n: 輸出一個回車換行符,Windows平臺為"\r\n",Unix平臺為"\n"輸出日志信息換行
           可以在%與模式字符之間加上修飾符來控制其最小寬度、最大寬度、和文本的對齊方式。如:
           1)%20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小于20的話,默認的情況下右對齊。
           2)%-20c:指定輸出category的名稱,最小的寬度是20,如果category的名稱小于20的話,"-"號指定左對齊。
           3)%.30c:指定輸出category的名稱,最大的寬度是30,如果category的名稱大于30的話,就會將左邊多出的字符截掉,但小于30的話也不會有空格。
           4)%20.30c:如果category的名稱小于20就補空格,并且右對齊,如果其名稱長于30字符,就從左邊較遠輸出的字符截掉。
          二.文件配置Sample1
          log4j.rootLogger=DEBUG,A1,R
          #log4j.rootLogger=INFO,A1,R
          # ConsoleAppender 輸出
          log4j.appender.A1=org.apache.log4j.ConsoleAppender
          log4j.appender.A1.layout=org.apache.log4j.PatternLayout
          log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
          # File 輸出 一天一個文件,輸出路徑可以定制,一般在根路徑下
          log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.R.File=blog_log.txt
          log4j.appender.R.MaxFileSize=500KB
          log4j.appender.R.MaxBackupIndex=10
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n
          文件配置Sample2
          下面給出的Log4J配置文件實現了輸出到控制臺,文件,回滾文件,發送日志郵件,輸出到數據庫日志表,自定義標簽等全套功能。
          log4j.rootLogger=DEBUG,CONSOLE,A1,im
          #DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE
          log4j.addivity.org.apache=true
          ###################
          # Console Appender
          ###################
          log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
          log4j.appender.Threshold=DEBUG
          log4j.appender.CONSOLE.Target=System.out
          log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
          log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n
          #####################
          # File Appender
          #####################
          log4j.appender.FILE=org.apache.log4j.FileAppender
          log4j.appender.FILE.File=file.log
          log4j.appender.FILE.Append=false
          log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          # Use this layout for LogFactor 5 analysis
          ########################
          # Rolling File
          ########################
          log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
          log4j.appender.ROLLING_FILE.Threshold=ERROR
          log4j.appender.ROLLING_FILE.File=rolling.log
          log4j.appender.ROLLING_FILE.Append=true
          log4j.appender.ROLLING_FILE.MaxFileSize=10KB
          log4j.appender.ROLLING_FILE.MaxBackupIndex=1
          log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          ####################
          # Socket Appender
          ####################
          log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
          log4j.appender.SOCKET.RemoteHost=localhost
          log4j.appender.SOCKET.Port=5001
          log4j.appender.SOCKET.LocationInfo=true
          # Set up for Log Facter 5
          log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
          log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
          ########################
          # Log Factor 5 Appender
          ########################
          log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
          log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
          ########################
          # SMTP Appender
          #######################
          log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
          log4j.appender.MAIL.Threshold=FATAL
          log4j.appender.MAIL.BufferSize=10
          log4j.appender.MAIL.From=chenyl@yeqiangwei.com
          log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
          log4j.appender.MAIL.Subject=Log4J Message
          log4j.appender.MAIL.To=chenyl@yeqiangwei.com
          log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
          log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          ########################
          # JDBC Appender
          #######################
          log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
          log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
          log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
          log4j.appender.DATABASE.user=root
          log4j.appender.DATABASE.password=
          log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
          log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
          log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A1.File=SampleMessages.log4j
          log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
          log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
          ###################
          #自定義Appender
          ###################
          log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
          log4j.appender.im.host = mail.cybercorlin.net
          log4j.appender.im.username = username
          log4j.appender.im.password = password
          log4j.appender.im.recipient = corlin@yeqiangwei.com
          log4j.appender.im.layout=org.apache.log4j.PatternLayout
          log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          三.高級使用
          實驗目的:
           1.把FATAL級錯誤寫入2000NT日志
           2. WARN,ERROR,FATAL級錯誤發送email通知管理員
           3.其他級別的錯誤直接在后臺輸出
          實驗步驟:
           輸出到2000NT日志
           1.把Log4j壓縮包里的NTEventLogAppender.dll拷到WINNT\SYSTEM32目錄下
           2.寫配置文件log4j.properties
          # 在2000系統日志輸出
           log4j.logger.NTlog=FATAL, A8
           # APPENDER A8
           log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
           log4j.appender.A8.Source=JavaTest
           log4j.appender.A8.layout=org.apache.log4j.PatternLayout
           log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
          3.調用代碼:
           Logger logger2 = Logger.getLogger("NTlog"); //要和配置文件中設置的名字相同
           logger2.debug("debug!!!");
           logger2.info("info!!!");
           logger2.warn("warn!!!");
           logger2.error("error!!!");
           //只有這個錯誤才會寫入2000日志
           logger2.fatal("fatal!!!");
          發送email通知管理員:
           1. 首先下載JavaMail和JAF,
            http://java.sun.com/j2ee/ja/javamail/index.html
            http://java.sun.com/beans/glasgow/jaf.html
           在項目中引用mail.jar和activation.jar。
           2. 寫配置文件
           # 將日志發送到email
           log4j.logger.MailLog=WARN,A5
           #  APPENDER A5
           log4j.appender.A5=org.apache.log4j.net.SMTPAppender
           log4j.appender.A5.BufferSize=5
           log4j.appender.A5.To=chunjie@yeqiangwei.com
           log4j.appender.A5.From=error@yeqiangwei.com
           log4j.appender.A5.Subject=ErrorLog
           log4j.appender.A5.SMTPHost=smtp.263.net
           log4j.appender.A5.layout=org.apache.log4j.PatternLayout
           log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
           3.調用代碼:
           //把日志發送到mail
           Logger logger3 = Logger.getLogger("MailLog");
           logger3.warn("warn!!!");
           logger3.error("error!!!");
           logger3.fatal("fatal!!!");
          在后臺輸出所有類別的錯誤:
           1. 寫配置文件
           # 在后臺輸出
           log4j.logger.console=DEBUG, A1
           # APPENDER A1
           log4j.appender.A1=org.apache.log4j.ConsoleAppender
           log4j.appender.A1.layout=org.apache.log4j.PatternLayout
           log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
           2.調用代碼
           Logger logger1 = Logger.getLogger("console");
           logger1.debug("debug!!!");
           logger1.info("info!!!");
           logger1.warn("warn!!!");
           logger1.error("error!!!");
           logger1.fatal("fatal!!!");
          --------------------------------------------------------------------
           全部配置文件:log4j.properties
           # 在后臺輸出
           log4j.logger.console=DEBUG, A1
           # APPENDER A1
           log4j.appender.A1=org.apache.log4j.ConsoleAppender
           log4j.appender.A1.layout=org.apache.log4j.PatternLayout
           log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
          # 在2000系統日志輸出
           log4j.logger.NTlog=FATAL, A8
           # APPENDER A8
           log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
           log4j.appender.A8.Source=JavaTest
           log4j.appender.A8.layout=org.apache.log4j.PatternLayout
           log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
          # 將日志發送到email
           log4j.logger.MailLog=WARN,A5
           #  APPENDER A5
           log4j.appender.A5=org.apache.log4j.net.SMTPAppender
           log4j.appender.A5.BufferSize=5
           log4j.appender.A5.To=chunjie@yeqiangwei.com
           log4j.appender.A5.From=error@yeqiangwei.com
           log4j.appender.A5.Subject=ErrorLog
           log4j.appender.A5.SMTPHost=smtp.263.net
           log4j.appender.A5.layout=org.apache.log4j.PatternLayout
           log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
          全部代碼:Log4jTest.java
           
          /*
            * 創建日期 2003-11-13
            */
           package edu.bcu.Bean;
           import org.apache.log4j.*;
           //import org.apache.log4j.nt.*;
           //import org.apache.log4j.net.*;
           /**
            * @author yanxu
            */
           public class Log4jTest
           {
            public static void main(String args[])
            {
             PropertyConfigurator.configure("log4j.properties");
             //在后臺輸出
             Logger logger1 = Logger.getLogger("console");
             logger1.debug("debug!!!");
             logger1.info("info!!!");
             logger1.warn("warn!!!");
             logger1.error("error!!!");
             logger1.fatal("fatal!!!");
          //在NT系統日志輸出
             Logger logger2 = Logger.getLogger("NTlog");
             //NTEventLogAppender nla = new NTEventLogAppender();
             logger2.debug("debug!!!");
             logger2.info("info!!!");
             logger2.warn("warn!!!");
             logger2.error("error!!!");
             //只有這個錯誤才會寫入2000日志
             logger2.fatal("fatal!!!");
          //把日志發送到mail
             Logger logger3 = Logger.getLogger("MailLog");
             //SMTPAppender sa = new SMTPAppender();
             logger3.warn("warn!!!");
             logger3.error("error!!!");
             logger3.fatal("fatal!!!");
            }
           }

          posted @ 2008-10-16 00:23 java民工 閱讀(729) | 評論 (0)編輯 收藏

          關于eclipse中編碼格式不能保存的問題

          Windows-->preference
          General->Content Type
          選擇對應的文件類型,然后下面修改為GBK或者gb2312,點update應該就可以了!

          posted @ 2008-10-16 00:21 java民工 閱讀(492) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 胶南市| 永济市| 富源县| 翼城县| 塔河县| 马边| 嘉鱼县| 镇原县| 宜章县| 盐津县| 塔城市| 大同市| 沈丘县| 柳州市| 鹤庆县| 元谋县| 合山市| 萨迦县| 二连浩特市| 仁化县| 永德县| 仙桃市| 大丰市| 大城县| 肥乡县| 仁寿县| 含山县| 江川县| 吉水县| 湘西| 甘德县| 东乡县| 松潘县| 嘉义县| 通许县| 景泰县| 马边| 新晃| 和林格尔县| 荔浦县| 贺州市|