DB2事務日誌使用經驗

 

 

  我們經常接到客戶的電話,我的數據庫日誌滿了,有沒有什麼好辦法快速清除?尤其對於一些初入門的DB2使用者去維護一個大數據量的系統,這幾乎是他們必然會碰到的一個問題。

  我們也經常接到客戶更緊急的電話,我的數據庫不能使用了,因爲日誌佔用太多空間,文件系統滿了,就把日誌刪除了,現在數據庫無法使用,這個是生產系統,需要儘快恢復,有什麼辦法可以讓數據庫立刻使用?

  碰到這樣的問題,我們可以不厭其煩的一遍遍向客戶解釋這個問題的原因,也可以給出非常明確的解決方案,但是對於很多客戶看來,這似乎是一個比較無奈的解決方案,他們只能承擔着這種操作帶來的系統中斷。

  因此,對於數據庫的設計人員,開發人員和維護人員來講,非常清楚的瞭解數據庫的日誌原理與合理的規劃一些操作以避免發生這樣的情況是非常重要的!下面,我們就對數據庫的日誌原理和使用中經常遇到的問題以及其解決方法跟大家分享下。

  1、DB2數據庫的日誌原理

  事務日誌記錄數據庫中所有對象和數據的改變,在早前版本中最大可達256G,其大小爲( logprimary + logsecond ) * logfilsiz,其中logprimary + logsecond的值小於或等於256,logfilsiz的最大爲262144,在9.5版本中,日誌最大已經可以達到512G,其中logfilsz的大小更改爲524286。

  DB2數據庫的日誌分爲主日誌和輔助日誌,其中主日誌在第一個連接到達數據庫或者數據庫被激活後立即分配,而輔助日誌在主日誌大小不夠的時候動態分配。所以需要注意一點,日誌所在的文件系統的大小必須大於主日誌文件與輔助日誌文件的大小之和。

  DB2數據庫有2種日誌配置方式,循環日誌與歸檔日誌。

  循環日誌:這是數據庫默認的日誌使用方式,主日誌用來記錄所有的更改,當事務提交後,日誌文件會被重用。當主日誌文件達到限制時,輔助日誌文件將被使用。這種日誌方式可以進行崩潰恢復和版本恢復,不能進行前滾恢復,不支持在線備份。

  當活動事務的使用空間超過主日誌和輔助日誌的限制或者日誌空間超過磁盤可使用空間,將會得到日誌滿的錯誤。

 

點擊查看大圖

 

  歸檔日誌:啓用logarchmetd1、logarchmetd2或打開logretain參數,注意,在9.5版本中,不推薦使用logretain參數,其所有的設置值將被忽略。在數據庫歸檔日誌規劃時,建議不再使用logretain的方法。日誌文件將不會被刪除-保持在線或者離線狀態。支持前滾恢復和在線備份。

 

點擊查看大圖

 

  疑問:歸檔日誌下,日誌一直保留,持續生成新日誌,爲什麼還會出現日誌滿的錯誤?

  歸檔日誌下,其可用的活動日誌大小依然受到主日誌與輔助日誌大小之和的限制,所以,即使在歸檔日誌下,日誌滿的場景與活動日誌下是完全一樣的。

[!--empirenews.page--]

  2、日誌使用中的問題與解決方法

  在日常使用中,我們遇到最多的問題就是日誌滿,現在用幾個實際的例子來看如何分析和解決日誌滿的問題,一般的,日誌滿可以分以下幾個場景:

  A、 環境準備,並介紹數據庫日誌使用大小評估方法:

  數據庫參數設置如下:

  日誌文件大小(4KB) (LOGFILSIZ) = 10000

  主日誌文件的數目 (LOGPRIMARY) = 3

  輔助日誌文件的數目 (LOGSECOND) = 2

  日誌總大小爲200M.

  創建測試用表: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2 "create table test_log(col int, col2 char(10)

  ,col3 timestamp,col4 varchar(100),col5 varchar(100),col6 varchar(100),col7 varch

  ar(100),col8 varchar(100))"

  DB20000I SQL命令成功完成。

  創建插入數據的存儲過程: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2 -td@ -vf proc_testlog.sql

  create procedure proc_testlog(v1 int)

  begin

  declare time int default 0;

  while (time < v1)

  do

  insert into test_log values(1,'testlog',current timestamp,'testlogtestlogte

  stlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestl

  og','testlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestl

  ogtestlogtestlogtestlog','testlogtestlogtestlogtestlogtestlogtestlogtestlogtestl

  ogtestlogtestlogtestlogtestlogtestlogtestlog','testlogtestlogtestlogtestlogtestl

  ogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlog','testlogtestl

  ogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogtestlogt

  estlog');

  set time = time + 1;

  end while;

  end

  DB20000I SQL命令成功完成。

  我們來評估下插入使用日誌的情況,以便構造日誌滿的場景,使用db2pd來查看事務日誌的使用。

  分別打開2個db2cmd會話窗口,在窗口1中我們執行:

  C:/Documents and Settings/administrator>db2 +c call proc_testlog(1)

  返回狀態 = 0

  會話2中執行: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> C:/Documents and Settings/administrator>db2pd -db sample -transactions

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:29:20

  Transactions:

  Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2

  Firstlsn Lastlsn LogSpace SpaceReserved TID

  AxRegCnt GXID

  0x7FC21A80 7 [000-00007] 2 7 WRITE 0x00000000 0x00000

  000 0x000027718800 0x000027718800 110 700 0x000000004F13

  1 0

  可以看到這個寫操作佔用的日誌大約爲700個字節,在回話1中再重複執行上面的命令,會話2中在看db2pd的輸出: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2pd -db sample -transactions

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:45:55

  Transactions:

  Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2

  Firstlsn Lastlsn LogSpace SpaceReserved TID

  AxRegCnt GXID

  0x7FC21A80 7 [000-00007] 2 8 WRITE 0x00000000 0x00000

  000 0x000028E385B8 0x000028E38806 154 1334 0x000000004F57

  1 0

  1334-700=634,我們可以這樣評估,單個事務每執行一次表插入,插入一行佔用的日誌約爲700字節,在一個事務中,插入多條記錄,插入一行記錄佔用的日誌約爲634字節,當然,實際上當插入多行時,日誌的大小會比計算值略大。

  使用這個方法可以根據業務運行情況來評估需要數據庫應該配置的日誌大小,也可以評估單個大事務需要的日誌空間。

  根據估算,200M總日誌大小,200*1024*1024/635=330781。因此可以一次插入大約33W記錄來構造日誌滿的場景。

[!--empirenews.page--]

  B、 事務日誌滿場景一:當前未提交的事務太大,超過日誌的限制。

  在會話1中執行:

  C:/Documents and Settings/administrator>db2 commit

  DB20000I SQL命令成功完成。

  提交前面未提交的事務。

  C:/Documents and Settings/administrator>db2 +c call proc_testlog(330000)

  SQL0964C 數據庫的事務日誌已滿。 SQLSTATE=57011

  這時候我打開另外一個session,執行一個不相關的插入操作。

  C:/Documents and Settings/administrator>db2 "insert into test values(1112,1,’sdfsdfsdfsdf’,’sdfsdfsdfsdfsdf’,’sdfsdfsdffsdfsd’)

  DB21034E 該命令被當作 SQL 語句來處理,因爲它是無效的“命令行處理器”命令。在

  SQL 處理期間,它返回:

  SQL0964C 數據庫的事務日誌已滿。 SQLSTATE=57011

  可以看到,當日志滿的時候其他的任何記日誌的操作都將不能進行,所以整個系統基本處於不可用的狀態,除非等事務回滾結束。

  OK,事務日誌滿的情況出現,現在我們就根據日誌滿的日誌,來逆向分析是哪個操作導致的該問題,分析步驟如下:

  首先,確定哪個應用的事務佔用了大量的日誌空間:

  在回話2中執行: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2pd -db sample -transactions

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:02:27

  Transactions:

  Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2

  Firstlsn Lastlsn LogSpace SpaceReserved TID

  AxRegCnt GXID

  …..

  0x7FC21A80 7 [000-00007] 2 10 WRITE 0x00000000 0x00000

  000 0x00003D86000C 0x000048C4FCD0 14014572 201955470 0x000000004F91

  1 0

  …..

  可以看到上面紅色部分, AppHandl爲7的應用的一個事務佔用了大量的日誌。如果有多個應用佔用了大量的日誌,我們可以按照下面的方法逐個分析,看每個應用是執行了什麼sql導致的佔用如此大的日誌。

  然後使用db2pd確定這個日誌執行了什麼語句導致佔用了大量的日誌: 


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2pd -db sample -applications

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:02:36

  Applications:

  Address AppHandl [nod-index] NumAgents CoorEDUID Status C-

  AnchID C-StmtUID L-AnchID L-StmtUID Appid

  WorkloadID WorkloadOccID

  …..

  0x7AED8080 7 [000-00007] 1 1572 UOW-Waiting 0

  0 185 1 *LOCAL.DB2.081111100729

  1 1

  …..

  Application handle爲7的應用,對應的L-AnchID爲185,L-StmtUID爲1。在回話2中繼續使用db2pd找到對應的sql語句:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> db2pd -db sample -dynamic

  …..

  Dynamic SQL Statements:

  Address AnchID StmtUID NumEnv NumVar NumRef NumExe Text

  0x7EA7D540 185 1 1 1 1 1 CALL proc_testlog(?)

  …

  對應AnchID爲185, StmtUID爲1的語句,是CALL proc_testlog(?),通過上面的分析,我們可以找到,是調用存儲過程proc_testlog導致佔用了大量的日誌,從而找出導致日誌滿的罪魁禍首。

  解決方案

  首先,儘量規避超大事務的操作,對於必須執行的這種大操作,可以考慮是否可以分解成幾個事務進行,如果可以,儘量分解爲小事務的方式進行;如果業務上不可以分解,是否可以考慮採用不記日誌的方式?比如,load代替insert?錶針對這個操作,暫時改爲不記日誌的方式等等。

  注意:當進行不記日誌的操作時,必須非常清楚這樣的操作的影響,比如,歸檔日誌下數據庫前滾的影響,hadr與複製的數據同步影響,操作失敗結果如何等等。

  其次,總有些我們無法預料的操作發生,可能某個維護人員某天發出一個不適當的命令,刪除了大量的數據,導致日誌滿,整個系統無法運行,如何規避這樣的操作帶來的系統運行影響呢?可以設置參數:max_log和DB2_FORCE_APP_ON_MAX_LOG註冊變量。

  max_log此參數指示一個事務可以消耗的主日誌空間的百分比。該值是爲 logprimary 配置參數指定的值的百分比。如果該值設置爲 0,那麼對一個事務可以消耗的總的主日誌空間的百分比沒有限制。我們可以配合設置DB2_FORCE_APP_ON_MAX_LOG註冊變量來規定如果應用程序違反了 max_log 配置,我們對該應用如何處理,DB2_FORCE_APP_ON_MAX_LOG設置爲true,則超過max_log的應用回被強制與數據庫斷開連接,事務將被回滾,並且將返回錯誤 SQL1224N。如果 DB2_FORCE_APP_ON_MAX_LOG 註冊表變量設置爲 FALSE,則違反了max_log設置的的事務將失敗,並返回錯誤 SQL0964N。該應用程序仍然可以提交在工作單元中由先前語句完成的工作,它也可以回滾已完成的工作以撤銷該工作單元。

  通過次設置我們可以保證即使有大事務操作,總有(1-max_log/100)*log_primary+log_second的日誌可以用來處理日常交易,從而避免系統中斷。

  注意: 由 max_log 配置參數施加的限制不適用於下列 DB2 命令:ARCHIVE LOG、BACKUP DATABASE、LOAD、REORG TABLE(聯機)、RESTORE DATABASE 和 ROLLFORWARD DATABASE。

[!--empirenews.page--]

  C、 事務日誌滿場景二:某個事務一直未提交,佔用的日誌不能被重用,導致日誌滿

  現在看另外一個場景,我在一個會話中執行了如下命令:

  C:/Documents and Settings/administrator>db2 +c call proc_testlog(3)

  SQL0964C 數據庫的事務日誌已滿。 SQLSTATE=57011

  顯然,數據庫日誌已滿,於是,根據上面的方法,我找是哪個事務佔用了日誌。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->C:/Documents and Settings/administrator>db2pd -db sample -transactions

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:10:12

  Transactions:

  Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2

  Firstlsn Lastlsn LogSpace SpaceReserved TID

  AxRegCnt GXID

  0x7FC21A80 12 [000-00012] 2 7 READ 0x00000000 0x00000

  000 0x000000000000 0x000000000000 0 0 0x0000000053A9

  1 0

  0x7FC22780 13 [000-00013] 3 0 READ 0x00000000 0x00000

  000 0x000000000000 0x000000000000 0 0 0x00000000538F

  1 0

  0x7FC23480 14 [000-00014] 4 0 READ 0x00000000 0x00000

  000 0x000000000000 0x000000000000 0 0 0x0000000053BE

  1 0

  0x7FC24180 15 [000-00015] 5 0 READ 0x00000000 0x00000

  000 0x000000000000 0x000000000000 0 0 0x000000005391

  1 0

  0x7FC24E80 16 [000-00016] 6 0 READ 0x00000000 0x00000

  000 0x000000000000 0x000000000000 0 0 0x000000005394

  1 0

  0x7FC25B80 17 [000-00017] 7 4 WRITE 0x00000000 0x00000

  000 0x0000538A93B7 0x0000538A9455 184 408 0x00000000539A

  很奇怪,從結果顯示,我沒有發現任何一個佔用大量日誌的應用程序,日誌的使用顯然都非常的小,那爲什麼日誌還會滿呢?我們再注意下佔用日誌的應用,查看下各自使用的日誌文件。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> C:/Documents and Settings/administrator>db2pd -db sample -logs

  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:12:34

  Logs:

  Current Log Number 4

  Pages Written 9498

  Method 1 Archive Status n/a

  Method 1 Next Log to Archive n/a

  Method 1 First Failure n/a

  Method 2 Archive Status n/a

  Method 2 Next Log to Archive n/a

  Method 2 First Failure n/a

  Address StartLSN State Size Pages Filename

  0x7FBECBD4 0x0000537F0000 0x00000000 10000 10000 S0000000.LOG

  0x7FBECC74 0x000055F00000 0x00000000 10000 10000 S0000001.LOG

  0x7FBECD14 0x000058610000 0x00000000 10000 10000 S0000002.LOG

  0x7EABB2F4 0x00005AD20000 0x00000000 10000 10000 S0000003.LOG

  0x7EABB394 0x00005D430000 0x00000000 10000 10000 S0000004.LOG

  分析發現,這個佔用日誌的應用的日誌開始lsn爲0x0000538A93B7,結束lsn爲0x0000538A9455,正好落在第一日誌文件中,因爲這個事務一直沒有被提交,所以S0000000.LOG一直不能被重用,這樣業務在將主日誌和輔助日誌用完後,無法重新開始使用日誌文件,導致出現日誌滿的錯誤。同樣,使用上面的方法,我們可以查找出這個Applications handle爲7的一直沒有提交的小事務執行的是什麼操作。

  上面的情況模擬方法:

  在一個回話中執行一個小事物,比如

  C:/Documents and Settings/administrator>db2 +c "insert into test values ( 1112,1, ’sdfsdfsdfsdf’ , ’sdfsdfsdfsdfsdf’ , ’sdfsdfsdffsdfsd’ )

  在另外一個回話中執行佔用事務比較大的操作,比如:db2 call proc_testlog(300000),在這個回話中的操作都及時提交,直到配置的日誌文件被使用完,再執行小操作db2 call proc_testlog(3),就可以出現上面的日誌滿的情況。

  解決方案:

  可以看出,不是日誌滿的問題一定是由於應用佔用大量的日誌導致的,一個被忽略的未提交的操作也可能導致系統的日誌無法被重用而導致日誌滿,在應用中,這是我們應該儘量避免的。但是總是如果無法保證所有的操作都及時的提交,我們可以設置num_log_span參數來規避這個問題,參數指定是否對一個事務可以跨越多少個日誌文件具有限制以及該限制是多少,當設置這個參數後,未提交的事務所在的日誌與當前日誌跨越的個數超過這個值,將被中斷,從而避免事務長時間存在導致系統日誌滿。另外大事務可以跨越的日誌也不能超過這個限制,所以當設置max_log和num_log_span後,一個事務所可以使用的事務日誌將取2者中比較小的值。

  當啓用了無限活動日誌空間時,max_log和 num_log_span 配置參數非常有用。如果打開了無限記錄(即,logsecondary 爲 -1),那麼事務數不受日誌文件數的上限(logprimary + logsecond)限制。當到達 logprimary 的值時,DB2 將開始歸檔活動日誌,而不是使事務失敗。這樣可能會導致問題,例如,有一個長期運行的事務,但一直未落實它(可能是由於應用程序不正確導致的)。如果出現這種情況,那麼活動日誌空間會不斷增長,從而可能使得崩潰恢復性能很差。爲了防止這樣,可以爲 max_log 和/或 num_log_span 配置參數指定值。

  注意:系統臨時表的使用,系統臨時表的數據操作是不記日誌的,但是表的定義是有少量日誌記錄的,所以,臨時表定義了一直沒操作,不提交也可能會引起部分小日誌的一直被佔用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章