數(shù)據(jù)庫(kù)工程師:DBA在系統(tǒng)設(shè)計(jì)開(kāi)發(fā)中的重要性
許多應(yīng)用系統(tǒng)的性能或穩(wěn)定性并不理想,這在系統(tǒng)上線后不久就逐漸變?yōu)榧值膯?wèn)題,造成這些問(wèn)題的原因,往往體現(xiàn)了一點(diǎn):開(kāi)發(fā)設(shè)計(jì)這些系統(tǒng)的人,對(duì)數(shù)據(jù)庫(kù)本身不是很了解!而DBA又不了解業(yè)務(wù)!這就導(dǎo)致了很多本來(lái)可以避免的問(wèn)題產(chǎn)生;另一方面,隨著數(shù)據(jù)庫(kù)自我調(diào)整、管理的能力不斷加強(qiáng),而應(yīng)用又往往是系統(tǒng)性能最大的殺手,所以,DBA的工作范疇,從只負(fù)責(zé)數(shù)據(jù)庫(kù)服務(wù)器維護(hù),逐步走向管理應(yīng)用系統(tǒng)的設(shè)計(jì)、開(kāi)發(fā),是必然的趨勢(shì)!
一、 現(xiàn)階段DBA對(duì)系統(tǒng)性能及穩(wěn)定性所做的調(diào)整工作
目前DBA對(duì)系統(tǒng)性能的調(diào)整工作大致是這么幾個(gè)方面:
1、 在硬件層面進(jìn)行調(diào)優(yōu),這通常就是直接花錢,買設(shè)備、擴(kuò)容。
2、 在DB層面進(jìn)行調(diào)優(yōu),比如調(diào)整初始化參數(shù),調(diào)整數(shù)據(jù)庫(kù)物理結(jié)構(gòu)。
3、 對(duì)應(yīng)用的SQL進(jìn)行優(yōu)化,比如在數(shù)據(jù)庫(kù)分析statspack,調(diào)整Top SQL。
4、 只有非常少數(shù)的,通常是對(duì)系統(tǒng)穩(wěn)定要求較高的一些公司的應(yīng)用,才會(huì)在新的應(yīng)用上線前,讓DBA對(duì)sql進(jìn)行充分的審核與評(píng)估。
問(wèn)題:在應(yīng)用系統(tǒng)的分析、設(shè)計(jì)、開(kāi)發(fā)階段,就目前情況看,很少有DBA參與,而應(yīng)用系統(tǒng)上線或者開(kāi)發(fā)工作基本結(jié)束后,DBA所能做的調(diào)優(yōu)工作其實(shí)是很有限的。
二、 許多應(yīng)用系統(tǒng)的性能或穩(wěn)定性仍不理想
許多應(yīng)用系統(tǒng)的性能并不理想,或者系統(tǒng)數(shù)據(jù)會(huì)出現(xiàn)一些難以重現(xiàn)的奇怪的錯(cuò)誤,這些問(wèn)題(尤其是性能問(wèn)題)有時(shí)并不是在系統(tǒng)初期就會(huì)體現(xiàn)出來(lái),但是隨著系統(tǒng)的運(yùn)行、數(shù)據(jù)的增多而逐步變得難以解決,給系統(tǒng)后期的功能擴(kuò)展和用戶使用上帶來(lái)了不少麻煩,造成這些問(wèn)題的原因,往往體現(xiàn)了一點(diǎn):開(kāi)發(fā)、設(shè)計(jì)這些系統(tǒng)的人不了解數(shù)據(jù)庫(kù)!以基于Oracle的應(yīng)用為例,簡(jiǎn)要舉例說(shuō)明:
底層數(shù)據(jù)結(jié)構(gòu)不合理
由于缺少專業(yè)DBA的協(xié)助,很多系統(tǒng)設(shè)計(jì)出來(lái)的底層數(shù)據(jù)庫(kù)表結(jié)構(gòu)問(wèn)題重重。而做過(guò)系統(tǒng)的人都知道,底層數(shù)據(jù)庫(kù)結(jié)構(gòu)不合理,帶來(lái)的改造代價(jià)之大幾乎等于一次重構(gòu)!我見(jiàn)過(guò)一個(gè)OLTP系統(tǒng),其核心表竟有100個(gè)字段,平均一條記錄超過(guò)8K,如果按Oracle默認(rèn)的8K一個(gè)Block,一半以上的行必須產(chǎn)生行鏈接!
而最糟糕的是,設(shè)計(jì)這樣表結(jié)構(gòu)的人還認(rèn)為自己充分利用了冗余來(lái)降低表之間的連接,事實(shí)上,其人根本不曉得什么是范式、什么是更新異常,按照范式,這個(gè)表應(yīng)該拆分為兩個(gè)表的,但如果要改幾乎所有的程序都要改!雖然范式不是越高越好,但絕對(duì)是設(shè)計(jì)的人必須吃透的一個(gè)東西。在冗余上,相信大多數(shù)DBA都認(rèn)為,級(jí)聯(lián)更新的代價(jià)是非常高的,因此冗余應(yīng)當(dāng)避免發(fā)生級(jí)聯(lián)更新的情況,對(duì)于關(guān)系型數(shù)據(jù)庫(kù)設(shè)計(jì)中冗余的使用,絕不是門很容易掌握的技巧。
不合理的底層數(shù)據(jù)庫(kù)結(jié)構(gòu)設(shè)計(jì),給系統(tǒng)的性能埋下了重磅的定時(shí)炸彈,這個(gè)系統(tǒng)在客戶那里跑不到一年,數(shù)據(jù)量稍微上去些,性能、穩(wěn)定性就直線下降,而重構(gòu)的成本又極高,買新服務(wù)器肯定是只能治標(biāo)。而假如底層數(shù)據(jù)表結(jié)構(gòu)是資深DBA設(shè)計(jì)的又會(huì)如何?當(dāng)然,如果完全讓DBA去做數(shù)據(jù)庫(kù)表結(jié)構(gòu)的設(shè)計(jì),DBA就必須非常清楚地了解整個(gè)系統(tǒng)的業(yè)務(wù)細(xì)節(jié)信息,這在DBA來(lái)說(shuō),人力資源上是有一定困難的,畢竟維護(hù)好線上服務(wù)器就已經(jīng)占用了DBA很多的資源,并且領(lǐng)導(dǎo)們通常更看重這點(diǎn)。
很少有領(lǐng)導(dǎo)能認(rèn)識(shí)到DBA在系統(tǒng)開(kāi)發(fā)設(shè)計(jì)中所起到的作用,和維護(hù)線上系統(tǒng)、處理DB故障相比,對(duì)整個(gè)系統(tǒng)的穩(wěn)定性和性能,是同樣重要的!
SQL性能問(wèn)題
系統(tǒng)的開(kāi)發(fā),通常和DBA是沒(méi)有什么關(guān)系的,但是,如果DBA對(duì)系統(tǒng)有足夠的了解,這時(shí)候也是可以做不少貢獻(xiàn)的。比如,檢查系統(tǒng)業(yè)務(wù)的數(shù)據(jù)流是否正確,這個(gè)需要通過(guò)一些手段,比如sqltrace、10046等,詳細(xì)對(duì)系統(tǒng)的邏輯實(shí)現(xiàn)進(jìn)行檢查,一方面查出系統(tǒng)中過(guò)于消耗資源的或編寫(xiě)不規(guī)范的SQL及時(shí)進(jìn)行調(diào)整優(yōu)化,另一方面,查出系統(tǒng)中不合理的數(shù)據(jù)庫(kù)訪問(wèn),不要到了線上才發(fā)現(xiàn)問(wèn)題,那時(shí)可能已經(jīng)宕機(jī)了。簡(jiǎn)單舉個(gè)例子,當(dāng)一個(gè)頁(yè)面需要多處顯示商品的類目列表時(shí),程序往往容易犯一個(gè)錯(cuò)誤,就是多次以同樣的SQL讀取出同樣的數(shù)據(jù),并應(yīng)用于每一個(gè)列表顯示上,如果你只讀取一次,或者干脆在Web層進(jìn)行cache(要有適當(dāng)?shù)乃⑿虏呗裕?,就可以大大減少單次訪問(wèn)該頁(yè)面在DB上的I/O消耗。有時(shí)甚至?xí)z查出根本不需要被執(zhí)行的SQL,也在這些和自己毫不相干的功能中頻繁地執(zhí)行著……同時(shí),對(duì)數(shù)據(jù)流的檢查還能夠查出一些隱藏得較深的系統(tǒng)Bug,這個(gè)更需要基于DBA對(duì)業(yè)務(wù)細(xì)節(jié)的了解。
誰(shuí)說(shuō)DBA只會(huì)花錢?如果一個(gè)服務(wù)器I/O負(fù)載達(dá)到極限,大多數(shù)人只能選擇擴(kuò)容,最多重構(gòu)部分功能來(lái)作些優(yōu)化,而從statspack往往可以看出,系統(tǒng)的I/O資源多數(shù)是被一些并不該如此頻繁執(zhí)行的SQL給占用了,它們單次執(zhí)行并不慢,但占用系統(tǒng)資源比例卻異常高,這些問(wèn)題,細(xì)化在每一個(gè)業(yè)務(wù)中,對(duì)這些問(wèn)題的檢查和數(shù)據(jù)流優(yōu)化,就是對(duì)系統(tǒng)資源的最大節(jié)省,就是省錢!這個(gè)工作,或許只有DBA才能稱職。
并發(fā)問(wèn)題
誰(shuí)都知道系統(tǒng)有并發(fā)存在,可是我們?cè)谠O(shè)計(jì)系統(tǒng)的時(shí)候,又往往是按照單一業(yè)務(wù)的思維模式來(lái)設(shè)計(jì)、編碼,很少考慮同一業(yè)務(wù)、不同業(yè)務(wù)之間并發(fā)運(yùn)作可能產(chǎn)生的問(wèn)題。通常,系統(tǒng)無(wú)規(guī)律地出現(xiàn)一些“奇怪的”、“不可能的”錯(cuò)誤,極有可能就是并發(fā)惹的禍,而背后的問(wèn)題,往往體現(xiàn)了設(shè)計(jì)人員不了解數(shù)據(jù)庫(kù)的鎖機(jī)制,無(wú)法和業(yè)務(wù)很好地結(jié)合。設(shè)計(jì)的人不了解數(shù)據(jù)庫(kù),而DBA又不了解業(yè)務(wù),這就導(dǎo)致了很多本來(lái)可以避免的問(wèn)題產(chǎn)生。
最經(jīng)典的就是Tom Kytes舉的酒店預(yù)定的例子,當(dāng)兩個(gè)服務(wù)員同時(shí)按下查找預(yù)定房間的按鈕,結(jié)果是兩個(gè)人都預(yù)訂到了同一間客房,這個(gè)問(wèn)題很經(jīng)典,在目前看來(lái)也很容易解決,不就是加上鎖么?但是,這只是一個(gè)例子,在你實(shí)際應(yīng)用的系統(tǒng)中,你這樣貿(mào)然地加上for update,又可能導(dǎo)致別的問(wèn)題!比如:死鎖。在一個(gè)復(fù)雜的業(yè)務(wù)系統(tǒng)中,死鎖不難見(jiàn)到,這個(gè)是設(shè)計(jì)者的設(shè)計(jì)漏洞,需要設(shè)計(jì)者全面衡量業(yè)務(wù)關(guān)系,然后對(duì)表的鎖定制定規(guī)則來(lái)盡量避免的。學(xué)會(huì)使用鎖來(lái)保證數(shù)據(jù)的完整性還是不夠的,還要靈活應(yīng)用鎖,適當(dāng)采用樂(lè)觀鎖定。
如果對(duì)于重要的業(yè)務(wù),一律免談,直接悲觀鎖定也是不可取的,會(huì)給系統(tǒng)的維護(hù)帶來(lái)一些問(wèn)題,某些業(yè)務(wù)這樣做甚至?xí)?lái)數(shù)據(jù)的大面積鎖定時(shí),在OLTP上的代價(jià)很高,嚴(yán)重影響系統(tǒng)并發(fā)能力。我曾經(jīng)碰到一個(gè)錯(cuò)誤數(shù)據(jù)的問(wèn)題,分析后,確定是兩個(gè)不同的業(yè)務(wù)間并發(fā),同時(shí)缺少必要的鎖定,而造成的錯(cuò)誤數(shù)據(jù)。但基于該業(yè)務(wù)的特殊性,加鎖的代價(jià)是昂貴的,在DBA的仔細(xì)追究下,確認(rèn)了可以通過(guò)樂(lè)觀鎖定也即提交時(shí)檢驗(yàn)的方式來(lái)達(dá)到兩全其美的目的。從這里可以看出,數(shù)據(jù)的健康和完整性,與系統(tǒng)的并發(fā)能力有時(shí)是矛盾的,但有經(jīng)驗(yàn)的DBA能夠教你如何獲取最佳方案,當(dāng)然,前提是DBA參與設(shè)計(jì)并熟悉業(yè)務(wù)。
系統(tǒng)架構(gòu)的問(wèn)題
DBA不是系統(tǒng)架構(gòu)師,但數(shù)據(jù)庫(kù)是一個(gè)應(yīng)用系統(tǒng)核心的部分,同時(shí),由于數(shù)據(jù)庫(kù)服務(wù)器不像應(yīng)用服務(wù)器那樣便于擴(kuò)展,因此往往也是整個(gè)系統(tǒng)性能的瓶頸所在,所以架構(gòu)師在設(shè)計(jì)系統(tǒng)架構(gòu)時(shí),應(yīng)該充分考慮DBA的意見(jiàn),要考慮到DBA對(duì)數(shù)據(jù)庫(kù)中的SQL進(jìn)行性能調(diào)整的便利性甚至是可行性!
否則就可能導(dǎo)致DBA及開(kāi)發(fā)團(tuán)隊(duì)對(duì)系統(tǒng)的性能問(wèn)題反應(yīng)過(guò)慢甚至束手無(wú)策!我曾經(jīng)見(jiàn)過(guò)一個(gè)架構(gòu),它無(wú)法實(shí)現(xiàn)oracle最普通的分頁(yè)SQL!綁定變量就根本不在考慮中!再就是有些第三方組件或架構(gòu),能夠幫助我們的系統(tǒng)生成SQL,這當(dāng)然很省事,能夠加快開(kāi)發(fā)速度,可是在這樣的系統(tǒng)中,DBA如果想要優(yōu)化一條SQL可能很難,因?yàn)殚_(kāi)發(fā)人員要修改的東西相對(duì)較多,修改的工作量大、耗時(shí)長(zhǎng),并且工作量多肯定就更容易帶來(lái)新的錯(cuò)誤!Oracle大師Tom Kytes也曾在經(jīng)典著作Export one on one中反對(duì)使用這種自動(dòng)產(chǎn)生SQL的組件或架構(gòu),這種東西很可能給你的系統(tǒng)帶來(lái)性能和維護(hù)上的問(wèn)題!
這些問(wèn)題,如果咨詢過(guò)資深DBA,相信會(huì)盡早發(fā)現(xiàn)并在架構(gòu)上得到修復(fù)或調(diào)整。而到了系統(tǒng)開(kāi)發(fā)的后期,架構(gòu)的問(wèn)題已經(jīng)很難做本質(zhì)的調(diào)整了。假如你的系統(tǒng)要求非常高效,并且并發(fā)訪問(wèn)較大,那么建議架構(gòu)師傾向于尊重DBA的意見(jiàn),這對(duì)整個(gè)系統(tǒng)的性能以及持續(xù)地調(diào)優(yōu)將非常重要。而DBA,對(duì)系統(tǒng)架構(gòu)也要有一定的認(rèn)識(shí),并明確自己在現(xiàn)有架構(gòu)中遇到的困難是什么。
三、 提高應(yīng)用系統(tǒng)的性能、穩(wěn)定性
除了DBA原本的DB調(diào)優(yōu)、SQL調(diào)優(yōu)、服務(wù)器維護(hù)等日常工作以外,擴(kuò)展DBA的工作范疇,強(qiáng)化DBA在系統(tǒng)開(kāi)發(fā)過(guò)程中的控制能力和決定權(quán)。
1、 讓DBA參與到需求分析中去,并充分理解用戶需求,從DB的角度來(lái)理解和考慮這些需求實(shí)現(xiàn)的成本。
2、 Schema的設(shè)計(jì)必須由DBA設(shè)計(jì)確定或者審核確定,這點(diǎn)也要求DBA必須了解業(yè)務(wù)系統(tǒng),才能整理出正確的、有良好擴(kuò)展性的E-R關(guān)系。
3、 讓DBA更深入的參與系統(tǒng)的設(shè)計(jì),盡可能地讓DBA了解應(yīng)用的業(yè)務(wù)設(shè)計(jì)細(xì)節(jié),這對(duì)于DBA審核數(shù)據(jù)流是起到?jīng)Q定性作用的,如果有條件,業(yè)務(wù)的數(shù)據(jù)流應(yīng)當(dāng)作為系統(tǒng)的文檔之一,以便將來(lái)的反復(fù)核查。
4、 在系統(tǒng)上線之前,由DBA審核sqltrace中的sql以及數(shù)據(jù)流邏輯,最好是能給出一些重要業(yè)務(wù)功能在DB成本(比如I/O)上的評(píng)估結(jié)果。
5、 系統(tǒng)上線后的性能監(jiān)控,及時(shí)作出調(diào)整甚至一定范圍內(nèi)重構(gòu)優(yōu)化數(shù)據(jù)訪問(wèn)邏輯。
如上所述,則DBA的人力資源必然不足,因此,細(xì)化DBA的工作,進(jìn)行分工是正確并且高效的,在一些公司,已經(jīng)將DBA分為專管線上服務(wù)器的產(chǎn)品DBA和專管開(kāi)發(fā)、參與系統(tǒng)設(shè)計(jì)的開(kāi)發(fā)DBA,從不同方面全面保障系統(tǒng)的穩(wěn)定和高效,值得借鑒!
【編輯推薦】