我們?nèi)绾巫鯯QL監(jiān)控
對于SQL,我們一般都說SQL審計,SQL優(yōu)化,很少談SQL監(jiān)控。確實也是,SQL是很難監(jiān)控的,因為一個復(fù)雜的系統(tǒng)中,每天SQL的執(zhí)行次數(shù)高達(dá)千萬級別,甚至數(shù)十?dāng)?shù)百億,執(zhí)行不同SQL的數(shù)量也可能高達(dá)數(shù)萬數(shù)十萬。如果大量的SQL是動態(tài)生成的或者沒有使用綁定變量,那么可能在幾分鐘內(nèi)就有數(shù)萬條不同的SQL在執(zhí)行。
在這樣的情況下,如果我們需要開發(fā)一個通用性的產(chǎn)品用于做SQL監(jiān)控是十分困難的。當(dāng)然如果我們的業(yè)務(wù)系統(tǒng)相對比較穩(wěn)定,需要監(jiān)控的SQL數(shù)量相對穩(wěn)定,針對這些SQL做針對性的監(jiān)控也是比較容易實現(xiàn)的。而事實上,對于大多數(shù)企業(yè)來說,我們需要監(jiān)控的數(shù)據(jù)庫系統(tǒng)有上百甚至上千套,業(yè)務(wù)系統(tǒng)也在不斷發(fā)生變更,在這種環(huán)境下,要實現(xiàn)通用的SQL監(jiān)控確實還是有難度的。
對于DBA來說,也會有一定的SQL語句監(jiān)控的需求,也都會掌握一些SQL語句監(jiān)控與分析的技巧。對于Oracle數(shù)據(jù)庫的DBA來說,我們已經(jīng)十分習(xí)慣于通過AWR報告的TOP SQL相關(guān)內(nèi)容來分析SQL的運(yùn)行情況,發(fā)現(xiàn)存在問題的SQL。不過這種分析只能算SQL優(yōu)化,而無法稱之為SQL監(jiān)控。
今天我們來探討一下SQL監(jiān)控的問題,隨著硬件、云平臺、數(shù)據(jù)庫技術(shù)以及應(yīng)用架構(gòu)的不斷優(yōu)化演進(jìn),一些完全因為硬件資源或者數(shù)據(jù)庫配置等引發(fā)的數(shù)據(jù)庫問題的比例相對較少了,而因為SQL引發(fā)的問題在運(yùn)維中的占比越來越高。對于SQL的監(jiān)控需求是一直存在的,而且需求的種類也五花八門。前陣子有個客戶提出需要了解隨意一條SQL在某個時間段內(nèi)的精確執(zhí)行次數(shù),問我們的D-SMART是否支持。另外一個客戶問我D-SMART是否支持對任意一條SQL的執(zhí)行計劃變化進(jìn)行跟蹤,發(fā)現(xiàn)問題及時報警。
實際上SQL監(jiān)控的目的依然是及時發(fā)現(xiàn)系統(tǒng)可能存在的風(fēng)險。我和第一個朋友聊了聊他需要做如此精確的監(jiān)控的目的是什么,他也說不出一個所以然來。實際上這個需求最好從應(yīng)用的角度去做,在應(yīng)用系統(tǒng)的模塊中通過鉤子進(jìn)行統(tǒng)計的成本是最低的,從數(shù)據(jù)庫去做可能成本太高。如果要從數(shù)據(jù)庫的角度去統(tǒng)計,其精準(zhǔn)度就要大打折扣了,因為數(shù)據(jù)庫的內(nèi)存中保存的SQL統(tǒng)計信息并不完整,因此我們?nèi)ゲ蓸拥臅r候會有誤差。當(dāng)某條SQL有一定時間沒有執(zhí)行的時候,很可能會從內(nèi)存統(tǒng)計緩沖區(qū)中被清除,下一次再出現(xiàn)的是可能從頭統(tǒng)計了。目前我們的TOP SQL采集工作也是5分鐘進(jìn)行一次,對這段時間內(nèi)比較活躍的SQL進(jìn)行一次統(tǒng)計。因為大型系統(tǒng)中的SQL數(shù)量可能會十分龐大,為了避免給生產(chǎn)系統(tǒng)帶來太大的負(fù)載,這種采集也必然是輕量級的,只采集一些十分重要的TOP SQL的詳細(xì)信息。
至于第二個需求,如果我們要對全量的SQL進(jìn)行執(zhí)行計劃的跟蹤,那肯定是不現(xiàn)實的,如果系統(tǒng)中存在幾萬條SQL,幾十萬個執(zhí)行計劃,采集一次的成本開銷之大,對于一些并發(fā)量較高,并且業(yè)務(wù)對SQL執(zhí)行延時的穩(wěn)定性要求較高的系統(tǒng)來說,是無法承受的。
Oracle數(shù)據(jù)庫的SQL語句都是存儲于共享內(nèi)存的CURSOR結(jié)構(gòu)中的,而不少開源、國產(chǎn)數(shù)據(jù)庫并不使用全局共享CURSOR的方式,CURSOR僅在會話內(nèi)共享。因此采集SQL語句與執(zhí)行計劃的接口并不十分完善,有些數(shù)據(jù)庫甚至還要開啟一些特殊的跟蹤功能才能實現(xiàn)。針對不同的數(shù)據(jù)庫產(chǎn)品,我們需要采取不同的手段來采集TOP SQL,因此SQL監(jiān)控的實現(xiàn)方式還是需要仔細(xì)去設(shè)計的。
另外一點,我們做SQL監(jiān)控的目的并不是SQL監(jiān)控本身,SQL監(jiān)控的目標(biāo)是防止SQL出現(xiàn)異常,從而導(dǎo)致數(shù)據(jù)庫系統(tǒng)出現(xiàn)問題。因此我們不能把SQL監(jiān)控當(dāng)初目標(biāo),而是把SQL監(jiān)控當(dāng)成一種手段和方法。因此在一個系統(tǒng)中,監(jiān)控某個時間段內(nèi)某條SQL的精確執(zhí)行次數(shù)在絕大多數(shù)場景中沒有任何意義,我們只需要知道某些可能影響系統(tǒng)的SQL語句的大致執(zhí)行數(shù)量、平均每次執(zhí)行的開銷以及執(zhí)行次數(shù)與開銷的歷史波動情況,就足以支撐我們所需要的運(yùn)維分析場景了。
而某條SQL語句的執(zhí)行計劃發(fā)生了變化,如果其執(zhí)行成本并無增加,對數(shù)據(jù)庫的穩(wěn)定運(yùn)行并無太大的影響,那么這種變化我們也無需實時發(fā)現(xiàn),只要在定期的審計中有所發(fā)現(xiàn),并能夠分析出其存在的潛在風(fēng)險就可以了。而因為執(zhí)行計劃的變化而導(dǎo)致了系統(tǒng)負(fù)載過高,系統(tǒng)性能下降,那么我們從其他一些方面也可以觀察到。我們利用數(shù)據(jù)庫可觀測性的一些其他側(cè)面能夠發(fā)現(xiàn)此類問題就可以了。比如我們可以通過整個系統(tǒng)的邏輯讀/物理的突然增加,CPU使用率的增加,活躍會話數(shù)的增加等相對容易觀察到,并且監(jiān)控成本比較低的可觀測性指標(biāo)也能夠發(fā)現(xiàn)因為SQL執(zhí)行計劃變壞導(dǎo)致的問題,并能夠通過分析定位,快速發(fā)現(xiàn)是因為SQL執(zhí)行計劃變壞導(dǎo)致了該問題。那么我們也就能解決這個問題了。
比如說在D-SMART中采用了關(guān)鍵SQL平均邏輯讀突增與每秒邏輯讀數(shù)量超出正常水平等兩種方式來發(fā)現(xiàn)相關(guān)的問題。我們以關(guān)鍵SQL平均邏輯讀突然增加的告警來看看D-SMART是如何分析這個問題的。
從SQL的歷史分析上看,確實出現(xiàn)了平均每次邏輯讀突變的情況。我們再來看看SQL的執(zhí)行計劃,是不是出現(xiàn)了多個執(zhí)行計劃。
從分析上看,確實出現(xiàn)了兩個不同子游標(biāo),其中一個游標(biāo)的執(zhí)行成本明顯大于另外一個。正是因為這個問題,導(dǎo)致了剛才那個告警的出現(xiàn)。這種方式是針對關(guān)鍵SQL的,關(guān)鍵SQL是一個系統(tǒng)中對應(yīng)用可用性或者SLA有著關(guān)鍵影響的SQL,我們可以在每個采樣周期都對其進(jìn)行監(jiān)控。因為一個系統(tǒng)中的關(guān)鍵SQL的數(shù)量不會很大,因此這種專項監(jiān)控的成本也不高。
而如果出問題的并不是關(guān)鍵SQL,而是隨便哪一條SQL,突然因為統(tǒng)計信息不準(zhǔn)確或者說表數(shù)據(jù)量的變化,亦或是系統(tǒng)變更后出現(xiàn)了應(yīng)用的BUG,從而引起了執(zhí)行計劃的變化,進(jìn)而導(dǎo)致了系統(tǒng)資源不足,引起關(guān)鍵SQL因為系統(tǒng)資源不足(內(nèi)存,CPU,IO等)而引發(fā)了性能問題。這種情況也是十分常見的。如果這條SQL出問題還沒有觸發(fā)系統(tǒng)資源不足,從而導(dǎo)致核心業(yè)務(wù)故障,那么這個問題并不一定需要馬上被捕捉到,并且進(jìn)行處置。
只需要在定期的SQL審計(比如每周)中發(fā)現(xiàn)這個問題,就完全可以解決。如果比較嚴(yán)重了,可能會導(dǎo)致系統(tǒng)故障,那么我們還是需要盡可能早的捕獲到此類問題。在D-SMART中我們針對邏輯讀突增、物理讀突增、R隊列突增、活躍會話數(shù)突增、同一條SQL的并發(fā)執(zhí)行量達(dá)到某個閾值(此類SQL執(zhí)行計劃異常后必然出現(xiàn)執(zhí)行時間過長,如果對系統(tǒng)產(chǎn)生較大影響,則大概率會出現(xiàn)多個SQL同時執(zhí)行的情況出現(xiàn))等,都會產(chǎn)生告警。并且在這些告警中,都可有執(zhí)行計劃發(fā)生變化的診斷路徑,可以用于根因溯源。這樣就采取了一種迂回策略,從一個側(cè)面解決了此類問題的預(yù)警問題。