程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> DB2事務日志使用經驗

DB2事務日志使用經驗

編輯:DB2教程

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

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

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

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

1、DB2數據庫的日志原理

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

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

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

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

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

DB2事務日志使用經驗

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

DB2事務日志使用經驗

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

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

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

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

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

數據庫參數設置如下:

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

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

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

日志總大小為200M.

創建測試用表: 

  C:Documents and Settingsadministrator>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命令成功完成。

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

  C:Documents and Settingsadministrator>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 Settingsadministrator>db2 +c call proc_testlog(1)

返回狀態 = 0

會話2中執行: 

  C:Documents and Settingsadministrator>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的輸出: 

  C:Documents and Settingsadministrator>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記錄來構造日志滿的場景。

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

在會話1中執行:

C:Documents and Settingsadministrator>db2 commit

DB20000I SQL命令成功完成。

提交前面未提交的事務。

C:Documents and Settingsadministrator>db2 +c call proc_testlog(330000)

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

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

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

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

SQL 處理期間,它返回:

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

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

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

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

在回話2中執行: 

  C:Documents and Settingsadministrator>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確定這個日志執行了什麼語句導致占用了大量的日志:  C:Documents and Settingsadministrator>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語句:

  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。

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

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

C:Documents and Settingsadministrator>db2 +c call proc_testlog(3)

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

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

  C:Documents and Settingsadministrator>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

很奇怪,從結果顯示,我沒有發現任何一個占用大量日志的應用程序,日志的使用顯然都非常的小,那為什麼日志還會滿呢?我們再注意下占用日志的應用,查看下各自使用的日志文件。C:Documents and Settingsadministrator>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 Settingsadministrator>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 配置參數指定值。

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved