數(shù)據(jù)庫的等待事件分析接口其實(shí)比我們想象的更豐富
?等待事件是數(shù)據(jù)庫十分重要的可觀測性接口,通過等待事件可以快速定位數(shù)據(jù)庫存在的問題,并及時(shí)掌握數(shù)據(jù)庫的運(yùn)行狀態(tài)。二十年前的時(shí)候,我給一家銀行做服務(wù)的時(shí)候,他們要求核心系統(tǒng)監(jiān)控,要求監(jiān)控人員每隔五分鐘查看一次是否存在異常等待事件,從而確保核心業(yè)務(wù)的正常。
Oracle是首先提供等待事件接口的數(shù)據(jù)庫產(chǎn)品,而現(xiàn)在很多數(shù)據(jù)庫也都提供了等待事件接口,只不過提供的能力有些差別。國慶假期七天時(shí)間里,我每天看一點(diǎn)SQL SERVER的資料,首先發(fā)現(xiàn)微軟的文檔功力真的十分了得,看SQL SERVER的資料甚至比看Oracle的資料還要舒服。其次我也發(fā)現(xiàn),SQL SERVER在等待事件接口方面也做的十分到位。
今天我就以O(shè)racle、SQL SERVER、openGauss、Polardb四個(gè)數(shù)據(jù)庫為例,分析一下這些數(shù)據(jù)庫的等待事件接口的特點(diǎn),以及如何使用這些接口來進(jìn)行系統(tǒng)診斷。談起他數(shù)據(jù)庫之前,我們先來看看等待事件分析的鼻祖Oracle提供了哪些等待事件。我還是用Oracle 11g這個(gè)經(jīng)典版本為例,雖然這個(gè)版本是十多年前推出的,不過在等待事件方面已經(jīng)十分完善了。
實(shí)際上不管是現(xiàn)在的Oracle數(shù)據(jù)庫還是其他一些支持等待事件分析的數(shù)據(jù)庫,都已經(jīng)和Oracle剛剛推出OWI的時(shí)候不同了,等待事件接口也豐富了很多。不過這些年里,我發(fā)現(xiàn)大家還在用20多年前OWI剛剛出現(xiàn)時(shí)的等待事件接口來分析數(shù)據(jù)庫系統(tǒng),并沒有去使用在某些分析場景下更為有效的一些新的接口數(shù)據(jù)。這是一種慣性,就像十多年前,我還習(xí)慣于使用v$session_wait視圖去分析會(huì)話的等待事件,而不像一些年輕的DBA一樣使用v$session。V$session_wait是Oracle在7.3.2版本中就推出的一個(gè)等待事件接口的視圖,也是最經(jīng)典的一個(gè)。不過這個(gè)視圖不是我們今天要討論的主角,因?yàn)槟壳皵?shù)據(jù)庫系統(tǒng)的等待事件分析的數(shù)據(jù)接口已經(jīng)極大豐富了。
我習(xí)慣于把等待事件接口數(shù)據(jù)分為明細(xì)數(shù)據(jù)、匯總數(shù)據(jù)、采樣數(shù)據(jù)以及這些數(shù)據(jù)的歷史數(shù)據(jù)。這些數(shù)據(jù)在不同的場景中能夠發(fā)揮不同的作用,用好了,可以滿足DBA的很多方面的分析工作。
明細(xì)數(shù)據(jù)是當(dāng)前等待事件的實(shí)時(shí)狀態(tài),對(duì)于做當(dāng)前的實(shí)時(shí)分析是十分有價(jià)值的。如果故障問題一直存在,則分析當(dāng)前的數(shù)據(jù)可以給我們一個(gè)直觀的反映。不過在使用v$session的時(shí)候,大家要注意一個(gè)問題,那就是Oracle的等待事件接口與其他數(shù)據(jù)庫有所不同。我們來看看有什么不同。
我們以往可能僅僅關(guān)注active狀態(tài)的會(huì)話,而很少去關(guān)注state,Oracle的v$session里顯示的等待事件不僅僅是顯示正在等待的,而且會(huì)顯示剛剛等待結(jié)束的,狀態(tài)。所以有時(shí)候我們看到的某個(gè)等待事件可能當(dāng)時(shí)已經(jīng)結(jié)束了,而不是正在發(fā)生,而有些則正在發(fā)生。注意到這個(gè)差別十分關(guān)鍵,可以幫助我們?cè)诩?xì)節(jié)上分析數(shù)據(jù)庫的等待事件。其他數(shù)據(jù)庫一旦結(jié)束某個(gè)等待事件,就會(huì)立即進(jìn)入IDLE狀態(tài),這樣在系統(tǒng)中,我們看到的更多的是IDLE。對(duì)等待事件相關(guān)視圖進(jìn)行多次查詢,可能會(huì)有較大的差異。作為DBA,我更喜歡Oracle的這種輸出接口的方式。因?yàn)榇蠖鄶?shù)情況下,我們不是需要了解準(zhǔn)確的實(shí)時(shí)狀態(tài),而是要了解在這個(gè)期間的一個(gè)大體趨勢,保留剛剛結(jié)束還沒有開始其他等待事件之前的狀態(tài)十分重要。
實(shí)際上明細(xì)數(shù)據(jù)更有助于分析當(dāng)前的實(shí)時(shí)狀態(tài),查找某個(gè)會(huì)話當(dāng)時(shí)存在的問題,或者某些會(huì)話引發(fā)的某個(gè)問題。而要了解系統(tǒng)當(dāng)期的等待事件的總體情況,從而發(fā)現(xiàn)系統(tǒng)存在的一些隱藏的很深的問題,往往需要統(tǒng)計(jì)數(shù)據(jù)。這也是DBA往往更容易從AWR報(bào)告中看到系統(tǒng)問題的所在,而不是通過v$session的主要原因。
在PG數(shù)據(jù)庫中pg_stat_activity提供了一部分會(huì)話等待事件的信息,不過缺少了等待時(shí)長。一些基于PG的開業(yè)或者國產(chǎn)數(shù)據(jù)庫里,也提供了這個(gè)視圖,同時(shí)還做了一些擴(kuò)展。
依賴于PolarDB的polar_monitor/polar_monitor_reload這兩個(gè)插件,我們可以獲得很多的原生態(tài)PG數(shù)據(jù)庫所沒有的監(jiān)控特性。其中最為重要的是,我們能夠獲得等待事件的等待時(shí)長的數(shù)據(jù)了。等待時(shí)長可以為運(yùn)維分析提供更為準(zhǔn)確的信息。這一點(diǎn)我前陣子發(fā)的幾篇關(guān)于openGauss的文章中也做了闡述。Polar_monitor插件為我們帶來了數(shù)個(gè)polar開頭的監(jiān)控視圖。其中就有我們鎖期待的polar_stat_activity,這個(gè)和pg_stat_activity近似的監(jiān)控接口有著我們需要的新數(shù)據(jù)。
SQL SERVER從2016(13.x)版本開始提供了一個(gè)dm_exec_session_wait_stats視圖,這個(gè)視圖可以提供類似v$session的數(shù)據(jù)接口。
Oracle實(shí)際上提供了十分豐富的等待事件統(tǒng)計(jì)信息,通過v$eventmetric,我們可以看到最近1分鐘的等待事件統(tǒng)計(jì)信息。
在這個(gè)系統(tǒng)接口里,我們可以看到每個(gè)等待事件在最近一分鐘內(nèi)的等待次數(shù),等待時(shí)間,等待的會(huì)話數(shù)量,以及前臺(tái)進(jìn)程的等待次數(shù)與總時(shí)長數(shù)據(jù)。這些數(shù)據(jù)都十分有利于我們?nèi)シ治瞿硞€(gè)等待事件在最近一分鐘發(fā)生的情況。
不過如果我們想了解等待事件在系統(tǒng)中的整體情況,v$eventmetric提供的信息是不夠的,我們還需要v$system_event的信息。
v$system_event提供了系統(tǒng)中按照等待事件類別的統(tǒng)計(jì)信息,這是一個(gè)從數(shù)據(jù)庫啟動(dòng)以來的統(tǒng)計(jì)值。如果我們針對(duì)這個(gè)視圖的數(shù)據(jù)做定期采樣,那么就可以掌握系統(tǒng)中等待事件的總體情況。這個(gè)采樣數(shù)據(jù)可以用于任意時(shí)段的等待事件總體分析。
在openGauss和PolarDB中也提供了類似的統(tǒng)計(jì)數(shù)據(jù)接口。openGauss的dbe_perf.wait_events提供了和Oracle類似的統(tǒng)計(jì)數(shù)據(jù),而且更為詳細(xì)。
因?yàn)閛penGauss不提供類似Oracle的histogram的信息,因此它提供了最大值,最小值這些統(tǒng)計(jì)值。雖然不如提供柱狀圖那么直觀,不過對(duì)于等待事件分析來說依然十分有價(jià)值。
SQL SERVER也提供了一個(gè)類似的統(tǒng)計(jì)數(shù)據(jù)接口dm_os_wait_stats。
可以看出,max_wait_time_ms這個(gè)字段也出現(xiàn)在了這里,觀察最大值對(duì)于分析等待事件來說十分關(guān)鍵。
上面兩種統(tǒng)計(jì)數(shù)據(jù)對(duì)于等待事件分析來說還不足夠,因?yàn)槲覀冎徽莆樟似骄担绻谝粋€(gè)數(shù)十萬甚至數(shù)百萬的等待事件中,有幾千個(gè)是異常的,那么我們無法從平均等待時(shí)間發(fā)現(xiàn)這幾千個(gè)數(shù)據(jù)的異常。而v$event_histogram補(bǔ)上了這個(gè)缺陷。
通過柱狀圖,我們可以了解各種等待時(shí)長的等待事件的統(tǒng)計(jì)數(shù)據(jù),從而發(fā)現(xiàn)在某個(gè)時(shí)段存在某個(gè)問題。這個(gè)接口也是一個(gè)從系統(tǒng)啟動(dòng)來的統(tǒng)計(jì)值。不過我們通過LAST_UPDATE_TIME就可以分析出某個(gè)柱狀圖的數(shù)據(jù)在我們分析的時(shí)間段內(nèi)是否被更新過。因此如果我們沒有定時(shí)采集這個(gè)數(shù)據(jù),我們還是能夠看出一些端倪的。當(dāng)然如果能夠?qū)崿F(xiàn)對(duì)這個(gè)數(shù)據(jù)的定期采集肯定是有益的。AWR會(huì)定期采集這個(gè)數(shù)據(jù)并加以保存,不過其采集粒度過于粗了一點(diǎn)。
有些數(shù)據(jù)如果要完全保存歷史的明細(xì)數(shù)據(jù)是十分困難的,因此往往會(huì)采用采樣的方式。Oracle針對(duì)v$session這個(gè)十分重要的數(shù)據(jù)會(huì)做1秒鐘為單位的動(dòng)態(tài)采樣。將活躍會(huì)話的全量采樣保存下來,openGauss、OceanBase等也做了類似的采樣。PolarDB在新版本中也將會(huì)提供類似的采樣。Oracle中,這個(gè)采樣可以通過v$active_session_history來訪問。不過大家要注意的是,既然是采樣數(shù)據(jù),那么就會(huì)遺漏一些的,1秒鐘雖然是比較短的采樣周期,不過還是會(huì)漏掉一些等待事件。不過如果某個(gè)問題一直在發(fā)生,采樣中大概率會(huì)抓到這個(gè)等待事件。
除了Oracle數(shù)據(jù)庫外,openGauss率先提供了類似ASH的數(shù)據(jù)接口,Oceanbase和PolarDB也緊隨其后。我想今后越來越多的國產(chǎn)數(shù)據(jù)庫也會(huì)提供類似的接口。因?yàn)檫@個(gè)接口對(duì)于分析數(shù)據(jù)庫的問題,特別是性能問題,是十分關(guān)鍵的。
除此之外,歷史數(shù)據(jù)也是我們分析問題最常用的,因?yàn)槲覀兘?jīng)常要分析以前的某個(gè)時(shí)段數(shù)據(jù)庫存在的問題,而不僅僅是做當(dāng)前分析。缺乏歷史事件積累,我們就無法進(jìn)行分析了。借助于AWR等成熟的數(shù)據(jù)采樣機(jī)制,Oracle提供了多種歷史數(shù)據(jù)的保存機(jī)制。我們?nèi)绻軌蚣右猿浞掷茫瑒t可以幫助我們解決很多的問題。
與Oracle相比,國產(chǎn)、開業(yè)數(shù)據(jù)庫這方面的數(shù)據(jù)接口還是比較少,我想這也是今后國產(chǎn)數(shù)據(jù)庫會(huì)加以改進(jìn)的地方。