大家好,我是sulny_ann,這期想跟大家分享一下我之前在面試?yán)锩鎲栠^比較難的數(shù)據(jù)庫相關(guān)的問題。
大家經(jīng)常也在調(diào)侃后端好像就是技術(shù)數(shù)據(jù)庫的增刪改查,所以作為后端開發(fā),你對應(yīng)數(shù)據(jù)庫這一塊掌握的怎么樣,是非常能看出你整個開發(fā)的技術(shù)能力水平。
接下來就分享 3 個我之前問到的關(guān)于數(shù)據(jù)庫的 3 個問題。
第一個問題就是如果一個事務(wù)當(dāng)中有更新操作,也有查詢操作,那我是先更新好呢?還是先查詢好?
很多小伙伴一聽到這個問題不知道我想考啥,我印象比較深刻就是這個候選人他還是比較聰明的,他還先問我一下,你這個更新操作依不依賴這個查詢的操作。我也提示了這兩個是沒有什么依賴關(guān)系的,所以這里我的重點是開啟了一個事物,那對于事物它肯定是要消耗資源的,那消耗的資源有哪些東西?
?文章來源地址http://www.zghlxwxcb.cn/news/detail-687937.html
?
?
有連接池,還有底層的鎖,那大家想一下,更新它可能是會持有什么鎖呢?有可能是行鎖,也有可能是間隙鎖,甚至可能是表鎖。那既然這個事物加鎖,那其他的事物只能在這些資源上去做一個等待,這就可能降低整個數(shù)據(jù)庫的并發(fā)性能。
?
?
?
?
所以這個問題應(yīng)該怎么去回答呢?其實在大部分的情況就應(yīng)該先去查詢,再去更新,但這里的查詢默認(rèn)是不會去加鎖的。如果先更新,再去查詢,如果這個查詢是一個慢SQL,那這個更新操作它持有的資源是會一直阻塞在這里。
?
?
?
?
那先查詢再更新,那你 select 就算是一個慢SQL,在這個查詢執(zhí)行過程當(dāng)中其實是沒有加鎖的,這能夠一定程度提升整個數(shù)據(jù)庫的并發(fā)能力。我之前在線上確實也做過類似的優(yōu)化,只要把他們執(zhí)行的順序稍微改一下,在一些并發(fā)比較高的接口確實能夠提升很大的性能。
?
?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
第二個問題就是我們經(jīng)常在設(shè)計數(shù)據(jù)庫表的時候,經(jīng)常會做一些字段的冗余,你覺得這樣做有什么優(yōu)缺點?
這其實也是非常常見的一種反范式設(shè)計。做字段冗余大部分情況下是為了便于去查詢,例如商品跟店鋪之間的關(guān)系,我可能有一個關(guān)系表,但是我在業(yè)務(wù)上有很多查詢,就是要基于店鋪去查詢他所有的商品,那難道每一次查詢都要去做一個join嗎?或者查兩次嗎?如果說我在商品這個表里面去加一個店鋪的字段,做這么一個字段的冗余就能夠很大程度提升整個查詢的性能。
那做字段冗余有什么缺點嗎?也有就是如果你要去更新這個關(guān)系,你可能要改多個地方,這個就有點類似于緩存的一致性問題,而且這種問題如果在同一個數(shù)據(jù)庫可能還比較好控制,如果是在多個數(shù)據(jù)庫,那你這個風(fēng)險就非常大了。
所以這里你還要看你的業(yè)務(wù)場景,就是查詢的占比比較高,還是寫的占比比較高。如果說是寫的占比比較高,那你這個帶來事物還有不一致的風(fēng)險可能會更大。
?
第三個問題確實也比較有挑戰(zhàn),就是我們的 MySQL 里面的 binlog 跟redolog,哪一個是先產(chǎn)生的?
這個問題大家又覺得我是想問什么東西呢?要回答好這個問題,你首先要知道 binlog 跟 read log 它們分別是用來干嘛的,解決什么問題的。
簡單介紹一下, MySQL 底層其實是分了好幾個結(jié)構(gòu)的,其中有 Server 層,還有 engine 層。?
?
?
?
?
binlog它就是產(chǎn)生在 Server 層,是用來記錄數(shù)據(jù)庫DML 產(chǎn)生的二進(jìn)制日志,主要是用來做主從主備他們之間的一些數(shù)據(jù)備份。
?
?
?
?
那 redolog 它是產(chǎn)生在 MySQL 的?engine?層的,主要是用來保證數(shù)據(jù)操作的原子性。那這兩種日志他們其實都有自己的一個緩沖區(qū)。
?
?
?
?
但是他們持久化一般都是分兩個步驟:先寫在操作系統(tǒng)的內(nèi)核區(qū),再去做一個刷盤操作。
?
?
?
如果對可行性要求比較高,那我們每次產(chǎn)生事物的時候都是去做一個持久化,但是我們一般情況只會考慮把它刷在操作系統(tǒng)的內(nèi)核層,因為這種情況是性能跟它的數(shù)據(jù)可靠性做一個折中,只要操作系統(tǒng)層面沒有宕機(jī),那這個數(shù)據(jù)一般是不會丟失的。
說到這里我們好像并沒回答這個問題,就是這兩個操作哪個先產(chǎn)生?那這里產(chǎn)生是站在什么角度?是站在磁盤的角度,還是說站在 MySQL 進(jìn)程的角度?如果說是進(jìn)程,他們兩個基本上是同時產(chǎn)生的,但是坐在磁盤的角度,其實redolog 它可能先產(chǎn)生,為什么說是可能呢?因為 binlog 他一定說是事物提交之后才會去做一個持久化。
?
?
?
但是 Redo log 它其實有多種刷盤的機(jī)制,例如 MySQL 層面,它提供了一個同步的參數(shù),你只要每次事務(wù)都操作,都去做一個提交,這個性能可能是比較差的。
但是它還有另外兩種刷盤的機(jī)制,它默認(rèn)有一個 1 秒鐘去刷新整個內(nèi)核緩沖區(qū)的一個進(jìn)程,那這個時候你就算事務(wù)沒有提交,它也會把緩沖區(qū)的這個redolog進(jìn)行刷盤操作。
?
?
?
?
那在這個過程當(dāng)中,可能事務(wù)還沒有提交,那 redolog 已經(jīng)放在磁盤上了。
當(dāng)然有些小伙伴可能會覺得如果這個過程當(dāng)中斷電了怎么辦?那會不會有 redolog,然后binlog不一致??這就是 MySQL 它為什么要去實現(xiàn)一個二階段提交這么一個過程,這里時間有限,就不去做過多展開了。
?
?
?
當(dāng)然不同的 MySQL 它底層的版本參數(shù)也會有一些不一樣,比如說它有些可能還是基于你事物提交多少個它就進(jìn)行一個刷盤,或者中間你可以去設(shè)計一個緩沖區(qū),容量達(dá)到多少它也會進(jìn)行一個強(qiáng)制刷盤。
這個在不同的 MySQL 版本之間,它們的默認(rèn)值,還有這些緩沖區(qū)的參數(shù)可能都不太一樣。然后這里很多同學(xué)可能就會想,我學(xué)這些有什么用,平時在工作當(dāng)中又用不上。
怎么說呢,還是有一定用途的,你會發(fā)現(xiàn)這些很多參數(shù)基本上都是在可用性跟性能之間去做一個選擇,所以如果你在特定的業(yè)務(wù)場景下,你確實是可以在數(shù)據(jù)庫層面去做這么一些調(diào)優(yōu)。這也是為什么很多高級的DBA,他必須要去了解一定的業(yè)務(wù)場景。可能站在開發(fā)的角度就覺得 DBA 你只要管好運(yùn)維就行了,你不用去關(guān)心我的業(yè)務(wù)。那同樣呢,開發(fā)其實也可以去基于你的業(yè)務(wù)場景去反向給 DBA 提供一些建議,可以去調(diào)整哪些參數(shù)?可能在大部分小伙伴的工作環(huán)境下,其實并沒有必要去調(diào)整這些東西,你的業(yè)務(wù)也可以正常的運(yùn)行,所以大家就沒有學(xué)習(xí)這些東西的積極性了。
?但是我認(rèn)為作為后端開發(fā),你還是要去了解底層的一些結(jié)構(gòu)的,這些配置的參數(shù)名你沒必要去記,但是你至少知道大概有這么一個東西,然后用的時候你可以快速的去查,然后學(xué)到這些東西,你還可以把這種比較好的思想應(yīng)用在你的項目實際的工作當(dāng)中,他很多思想跟設(shè)計哲學(xué)其實是可以借鑒過來的,這也是我們對于技術(shù)專家和架構(gòu)師他需要的一個通用能力。
好,這一期就分享我之前在面試當(dāng)中問到這幾個數(shù)據(jù)庫比較復(fù)雜的問題,如果大家認(rèn)為寫的還不錯,也希望大家點贊轉(zhuǎn)發(fā),沒關(guān)注的小伙伴也別忘了關(guān)注下,后面就不會錯過很多技術(shù)的干貨了。文章來源:http://www.zghlxwxcb.cn/news/detail-687937.html
?
到了這里,關(guān)于架構(gòu)師必會之-DBA級問題的數(shù)據(jù)庫底層設(shè)計思想的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!