DB2事務日誌使用經驗

責任編輯:曉熊    做者: IT168 徐曉鋒   2008-11-24  
  咱們常常接到客戶的電話,個人數據庫日誌滿了,有沒有什麼好辦法快速清除?尤爲對於一些初入門的DB2使用者去維護一個大數據量的系統,這幾乎是他們必然會碰到的一個問題。
  咱們也常常接到客戶更緊急的電話,個人數據庫不能使用了,由於日誌佔用太多空間,文件系統滿了,就把日誌刪除了,如今數據庫沒法使用,這個是生產系統,須要儘快恢復,有什麼辦法可讓數據庫馬上使用?
  碰到這樣的問題,咱們能夠不厭其煩的一遍遍向客戶解釋這個問題的緣由,也能夠給出很是明確的解決方案,可是對於不少客戶看來,這彷佛是一個比較無奈的解決方案,他們只能承擔着這種操做帶來的系統中斷。
  所以,對於數據庫的設計人員,開發人員和維護人員來說,很是清楚的瞭解數據庫的日誌原理與合理的規劃一些操做以免發生這樣的狀況是很是重要的!下面,咱們就對數據庫的日誌原理和使用中常常遇到的問題以及其解決方法跟你們分享下。
  一、DB2數據庫的日誌原理
  事務日誌記錄數據庫中全部對象和數據的改變,在早前版本中最大可達256G,其大小爲( logprimary + logsecond ) * logfilsiz,其中logprimary + logsecond的值小於或等於256,logfilsiz的最大爲262144,在9.5版本中,日誌最大已經能夠達到512G,其中logfilsz的大小更改成524286。
  DB2數據庫的日誌分爲主日誌和輔助日誌,其中主日誌在第一個鏈接到達數據庫或者數據庫被激活後當即分配,而輔助日誌在主日誌大小不夠的時候動態分配。因此須要注意一點,日誌所在的文件系統的大小必須大於主日誌文件與輔助日誌文件的大小之和。
  DB2數據庫有2種日誌配置方式,循環日誌與歸檔日誌。
  循環日誌:這是數據庫默認的日誌使用方式,主日誌用來記錄全部的更改,當事務提交後,日誌文件會被重用。當主日誌文件達到限制時,輔助日誌文件將被使用。這種日誌方式能夠進行崩潰恢復和版本恢復,不能進行前滾恢復,不支持在線備份。
  當活動事務的使用空間超過主日誌和輔助日誌的限制或者日誌空間超過磁盤可以使用空間,將會獲得日誌滿的錯誤。
DB2事務日誌使用經驗
  歸檔日誌:啓用logarchmetd一、logarchmetd2或打開logretain參數,注意,在9.5版本中,不推薦使用logretain參數,其全部的設置值將被忽略。在數據庫歸檔日誌規劃時,建議再也不使用logretain的方法。日誌文件將不會被刪除-保持在線或者離線狀態。支持前滾恢復和在線備份。
DB2事務日誌使用經驗
  疑問:歸檔日誌下,日誌一直保留,持續生成新日誌,爲何還會出現日誌滿的錯誤?
  歸檔日誌下,其可用的活動日誌大小依然受到主日誌與輔助日誌大小之和的限制,因此,即便在歸檔日誌下,日誌滿的場景與活動日誌下是徹底同樣的。
  二、日誌使用中的問題與解決方法
  在平常使用中,咱們遇到最多的問題就是日誌滿,如今用幾個實際的例子來看如何分析和解決日誌滿的問題,通常的,日誌滿能夠分如下幾個場景:
  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 配置參數指定值。
  注意:系統臨時表的使用,系統臨時表的數據操做是不記日誌的,可是表的定義是有少許日誌記錄的,因此,臨時表定義了一直沒操做,不提交也可能會引發部分小日誌的一直被佔用。
相關文章
相關標籤/搜索