這篇文章將為大家詳細(xì)講解有關(guān)數(shù)據(jù)庫(kù)知識(shí)都有哪些,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名申請(qǐng)、虛擬主機(jī)、營(yíng)銷軟件、網(wǎng)站建設(shè)、保山網(wǎng)站維護(hù)、網(wǎng)站推廣。
大多數(shù)計(jì)算機(jī)系統(tǒng)都是有狀態(tài)的,并且可能會(huì)依賴存儲(chǔ)系統(tǒng)。隨著時(shí)間的推移,我對(duì)數(shù)據(jù)庫(kù)的了解程度不斷加深,這是以我們的設(shè)計(jì)錯(cuò)誤導(dǎo)致數(shù)據(jù)丟失和中斷為代價(jià)。在數(shù)據(jù)量很大的系統(tǒng)中,數(shù)據(jù)庫(kù)是系統(tǒng)設(shè)計(jì)目標(biāo)的核心。盡管開發(fā)人員不可能對(duì)數(shù)據(jù)庫(kù)一無(wú)所知,但他們所預(yù)見和所經(jīng)歷的問(wèn)題往往只是冰山一角。我將分享一些見解,這些見解對(duì)于不擅長(zhǎng)數(shù)據(jù)庫(kù)領(lǐng)域的開發(fā)人員來(lái)說(shuō)非常有用。
現(xiàn)如今,一方面人們認(rèn)為網(wǎng)絡(luò)很可靠,一方面由于網(wǎng)絡(luò)中斷而導(dǎo)致系統(tǒng)宕機(jī)的情況卻又很普遍。這方面的研究工作并不多,而且通常由大公司主導(dǎo),而這些公司使用了配備定制硬件的專用網(wǎng)絡(luò)和專門的工作人員。
谷歌服務(wù)的可用性為 99.999%,他們聲稱只有 7.6% 的 Spanner(谷歌的分布式數(shù)據(jù)庫(kù)) 問(wèn)題是因?yàn)榫W(wǎng)絡(luò)導(dǎo)致的,盡管他們一直認(rèn)為專用網(wǎng)絡(luò)是其可用性背后的核心支撐。2014 年,Bailis 和 Kingsbury 的一份調(diào)查報(bào)告對(duì) Peter Deutsch 在 1994 年提出的分布式計(jì)算謬論之一提出了挑戰(zhàn)——網(wǎng)絡(luò)真的可靠嗎?
我們無(wú)法進(jìn)行全面的調(diào)查,供應(yīng)商們也不會(huì)提供足夠的數(shù)據(jù)來(lái)說(shuō)明有多少客戶的問(wèn)題是因?yàn)榫W(wǎng)絡(luò)導(dǎo)致的。我們經(jīng)常會(huì)遭遇大型云供應(yīng)商網(wǎng)絡(luò)發(fā)生宕機(jī),導(dǎo)致部分網(wǎng)絡(luò)癱瘓數(shù)小時(shí),這些事件有大量可見的受影響客戶,還有很多是我們看不到的。網(wǎng)絡(luò)中斷可能會(huì)影響到更多方面,盡管并非所有事件都產(chǎn)生了很大的影響。云計(jì)算客戶也不一定能看到這些問(wèn)題所在。當(dāng)問(wèn)題出現(xiàn)時(shí),他們不太可能認(rèn)為與供應(yīng)商的網(wǎng)絡(luò)錯(cuò)誤有關(guān)。對(duì)他們來(lái)說(shuō),第三方服務(wù)就是黑盒。如果你不是供應(yīng)商,要估計(jì)出真實(shí)的影響程度是不太可能的。
與供應(yīng)商的報(bào)告相比,如果你的系統(tǒng)只有一小部分宕機(jī)與網(wǎng)絡(luò)問(wèn)題有關(guān),那你是幸運(yùn)的。網(wǎng)絡(luò)仍然受傳統(tǒng)問(wèn)題的影響,比如硬件故障、拓?fù)渥兏?、管理配置變更和電源故障。但最近我才知道,一些新發(fā)現(xiàn)的問(wèn)題(比如鯊魚咬斷海底光纜)也成了主要影響因素。
ACID 代表原子性、一致性、隔離性和持久性。即使在發(fā)生崩潰、錯(cuò)誤、硬件故障等類似事件時(shí),數(shù)據(jù)庫(kù)也需要保證這些屬性是有效的。大多數(shù)關(guān)系型事務(wù)數(shù)據(jù)庫(kù)都盡量提供 ACID 保證,但很多 NOSQL 數(shù)據(jù)庫(kù)是沒(méi)有 ACID 事務(wù)保證的,因?yàn)閷?shí)現(xiàn)成本很高。
在我剛進(jìn)入這個(gè)行業(yè)時(shí),我們的技術(shù)主管懷疑 ACID 是不是一個(gè)過(guò)時(shí)的概念??梢哉f(shuō),ACID 被認(rèn)為是一個(gè)種泛泛而談的概念,而不是一個(gè)嚴(yán)格的執(zhí)行標(biāo)準(zhǔn)?,F(xiàn)在,我發(fā)現(xiàn)它非常有用,因?yàn)樗峁┝艘活悊?wèn)題和一類潛在的解決方案。
并不是每個(gè)數(shù)據(jù)庫(kù)都兼容 ACID,而且在兼容 ACID 的數(shù)據(jù)庫(kù)當(dāng)中,對(duì) ACID 的解釋也可能存在差異。之所以存在差異,其中一個(gè)原因是在實(shí)現(xiàn) ACID 時(shí)涉及的權(quán)衡程度的不同。數(shù)據(jù)庫(kù)可能宣稱自己兼容 ACID,但對(duì)于一些邊緣情況,或者在面對(duì)“不太可能”出現(xiàn)的問(wèn)題時(shí),處理方式有所不同。
MongoDB 的 ACID 表現(xiàn)一直飽受爭(zhēng)議,即使是在發(fā)布了 v4 版本之后。MongoDB 在很長(zhǎng)一段時(shí)間內(nèi)都不支持日志記錄。對(duì)于下面這種情況,應(yīng)用程序進(jìn)行了兩次寫操作 (w1 和 w2),MongoDB 能夠持久化 w1,但因?yàn)榘l(fā)生硬件故障,導(dǎo)致無(wú)法持久化 w2。
MongoDB 在將數(shù)據(jù)寫入物理磁盤之前發(fā)生崩潰,造成數(shù)據(jù)丟失
將數(shù)據(jù)提交到磁盤是一個(gè)開銷很大的過(guò)程,它們聲稱寫入性能良好,卻是以避免頻繁提交數(shù)據(jù)為代價(jià),從而犧牲了持久性?,F(xiàn)在,MongoDB 有了日志記錄,但臟寫仍然會(huì)影響數(shù)據(jù)的持久性,因?yàn)槟J(rèn)情況下每 100 毫秒才提交一次日志。即使風(fēng)險(xiǎn)大大降低,日記記錄的持久性和變更仍然有可能出現(xiàn)同樣的問(wèn)題。
在 ACID 這幾個(gè)屬性中,一致性和隔離級(jí)別的實(shí)現(xiàn)方式是最多的,因?yàn)闄?quán)衡范圍最大。為了保持?jǐn)?shù)據(jù)一致性,數(shù)據(jù)庫(kù)需要進(jìn)行協(xié)調(diào),爭(zhēng)用資源的情況會(huì)增加。當(dāng)需要在多個(gè)數(shù)據(jù)中心之間進(jìn)行水平伸縮時(shí) (特別是在不同的地理區(qū)域之間),就變得非常困難。隨著可用性的降低和網(wǎng)絡(luò)分區(qū)的頻繁出現(xiàn),提供高水平的一致性是非常困難的。關(guān)于這一問(wèn)題的深入解釋,請(qǐng)參見 CAP 定理。不過(guò)需要注意的是,應(yīng)用程序可以在數(shù)據(jù)一致性方面做一些處理,或者程序員可能對(duì)這個(gè)問(wèn)題有足夠的了解,可以在應(yīng)用程序中添加額外的邏輯來(lái)處理,而不是嚴(yán)重依賴數(shù)據(jù)庫(kù)。
數(shù)據(jù)庫(kù)通常會(huì)提供各種隔離級(jí)別,應(yīng)用程序開發(fā)人員可以根據(jù)權(quán)衡選擇最經(jīng)濟(jì)有效的隔離級(jí)別。較弱的隔離級(jí)別可能速度更快,但可能會(huì)引入數(shù)據(jù)競(jìng)態(tài)問(wèn)題。更強(qiáng)的隔離級(jí)別消除了一些潛在的數(shù)據(jù)競(jìng)態(tài)問(wèn)題,但速度較慢,并且可能會(huì)引入資源爭(zhēng)用,使數(shù)據(jù)庫(kù)慢到宕機(jī)。
現(xiàn)有并發(fā)模型及其之間關(guān)系的概覽
SQL 標(biāo)準(zhǔn)只定義了 4 個(gè)隔離級(jí)別,盡管在理論方面和實(shí)際當(dāng)中都還有更多可用的級(jí)別。如果你想進(jìn)一步了解,jepson.io 提供了更多對(duì)現(xiàn)有并發(fā)模型的介紹。谷歌的 Spanner 保證了時(shí)鐘同步的外部串行性,即使這是一個(gè)更嚴(yán)格的隔離級(jí)別,但它在標(biāo)準(zhǔn)隔離級(jí)別中并沒(méi)有定義。
SQL 標(biāo)準(zhǔn)中提到的隔離級(jí)別是:
串行化 (最嚴(yán)格、成本最高):串行化執(zhí)行的效果與事務(wù)的串行執(zhí)行是一樣的。串行執(zhí)行是指每個(gè)事務(wù)在下一個(gè)事務(wù)開始之前執(zhí)行完成。需要注意的是,由于在解釋上的差異,串行化通常被實(shí)現(xiàn)成“快照隔離”(例如 Oracle),但在 SQL 標(biāo)準(zhǔn)中并沒(méi)有“快照隔離”。
可重復(fù)讀:當(dāng)前事務(wù)中未提交的讀取對(duì)當(dāng)前事務(wù)可見,但其他事務(wù)所做的更改 (如新插入的行) 不可見。
讀已提交:未提交的讀取對(duì)事務(wù)不可見。只有提交的寫是可見的,但可能會(huì)發(fā)生幻讀取。如果另一個(gè)事務(wù)插入和提交新行,當(dāng)前事務(wù)在查詢時(shí)可以看到它們。
讀未提交 (最不嚴(yán)格、成本最低):允許臟讀,事務(wù)可以看到其他事務(wù)未提交的更改。實(shí)際上,這個(gè)級(jí)別對(duì)于返回近似聚合很有用,比如 COUNT(*) 查詢。
串行化級(jí)別將發(fā)生數(shù)據(jù)競(jìng)爭(zhēng)的機(jī)會(huì)降到最低,盡管它的開銷最大,并給系統(tǒng)帶來(lái)了最多的爭(zhēng)用。其他隔離級(jí)別開銷較小,但增加了數(shù)據(jù)競(jìng)爭(zhēng)的可能性。有些數(shù)據(jù)庫(kù)允許設(shè)置隔離級(jí)別,有些數(shù)據(jù)庫(kù)不一定支持所有的隔離級(jí)別。
各種數(shù)據(jù)庫(kù)對(duì)隔離級(jí)別的支持情況
使用數(shù)據(jù)庫(kù)鎖的成本是非常高的,它們不僅引入了更多的爭(zhēng)用,而且要求應(yīng)用程序服務(wù)器和數(shù)據(jù)庫(kù)之間保持穩(wěn)定的連接。排它鎖受網(wǎng)絡(luò)分區(qū)的影響更大,并會(huì)導(dǎo)致難以識(shí)別和解決的死鎖。在這種情況下,可以考慮使用樂(lè)觀鎖。
樂(lè)觀鎖是指在讀取一行數(shù)據(jù)時(shí),記下它的版本號(hào)、最近修改的時(shí)間戳或校驗(yàn)和。然后,你可以在修改記錄之前檢查版本有沒(méi)有發(fā)生變化。
UPDATE products SET name = 'Telegraph receiver', version = 2 WHERE id = 1 AND version = 1
如果之前有一個(gè)更新操作修改了 products 表,那么當(dāng)前的更新操作將不修改任何數(shù)據(jù)。如果之前沒(méi)有被修改,當(dāng)前的更新操作將修改一行數(shù)據(jù)。
在討論數(shù)據(jù)一致性時(shí),我們主要關(guān)注可能會(huì)導(dǎo)致臟讀和數(shù)據(jù)丟失的競(jìng)態(tài)條件。但除了這些,我們還要注意異常數(shù)據(jù)。
這類異常的一個(gè)例子是寫傾斜(write skew)。寫傾斜并不是在進(jìn)行寫操作時(shí)發(fā)生臟讀或數(shù)據(jù)丟失時(shí)出現(xiàn)的,而是在數(shù)據(jù)的邏輯約束被破壞時(shí)出現(xiàn)的。
例如,假設(shè)有一個(gè)監(jiān)控應(yīng)用程序,要求至少有一個(gè)運(yùn)維人員可以隨叫隨到。
對(duì)于上述情況,如果兩個(gè)事務(wù)成功提交,就會(huì)出現(xiàn)寫傾斜。即使沒(méi)有發(fā)生臟讀或數(shù)據(jù)丟失,數(shù)據(jù)的完整性也會(huì)丟失,因?yàn)橛袃蓚€(gè)人被指派隨叫隨到。
串行化化隔離級(jí)別、模式設(shè)計(jì)或數(shù)據(jù)庫(kù)約束可能有助于消除寫傾斜。開發(fā)人員需要在開發(fā)期間識(shí)別出這些異常,避免在生產(chǎn)環(huán)境中出現(xiàn)這個(gè)問(wèn)題。話雖如此,直接從代碼中識(shí)別出寫傾斜是非常困難的。特別是在大型的系統(tǒng)中,如果不同的團(tuán)隊(duì)使用相同的表,但沒(méi)有相互溝通,也沒(méi)有檢查如何訪問(wèn)數(shù)據(jù),就更難發(fā)現(xiàn)問(wèn)題了。
數(shù)據(jù)庫(kù)提供的核心功能之一是順序保證,但這也是讓應(yīng)用程序開發(fā)人員感到驚訝的一個(gè)地方。數(shù)據(jù)庫(kù)按照接收事務(wù)的順序來(lái)安排順序,而不是按照代碼中所寫的事務(wù)順序來(lái)安排順序。事務(wù)執(zhí)行的順序很難預(yù)測(cè),特別是在大規(guī)模并發(fā)系統(tǒng)中。
在開發(fā)過(guò)程中,特別是在使用非阻塞開發(fā)庫(kù)時(shí),糟糕的可讀性可能會(huì)導(dǎo)致出現(xiàn)這樣的問(wèn)題:用戶認(rèn)為事務(wù)是按順序執(zhí)行的,但事務(wù)可能以任意順序到達(dá)數(shù)據(jù)庫(kù)。下面的代碼看起來(lái)像是要順序地調(diào)用 T1 和 T2,但如果這些函數(shù)是非阻塞的,并且會(huì)立即返回 promise,那么實(shí)際的調(diào)用順序?qū)⒂伤鼈兊竭_(dá)數(shù)據(jù)庫(kù)的時(shí)間決定。
result1 = T1() // 返回的是promise result2 = T2()
如果原子性是必需的 (完全提交或中止所有操作),而且順序很重要,那么 T1 和 T2 應(yīng)該包含在單個(gè)數(shù)據(jù)庫(kù)事務(wù)中。
分片是對(duì)數(shù)據(jù)庫(kù)進(jìn)行水平分區(qū)的一種方法。盡管有些數(shù)據(jù)庫(kù)可以自動(dòng)對(duì)數(shù)據(jù)進(jìn)行水平分區(qū),但有些數(shù)據(jù)庫(kù)不會(huì)這么做,或者可能不擅長(zhǎng)這么做。當(dāng)數(shù)據(jù)架構(gòu)師或開發(fā)人員能夠預(yù)測(cè)數(shù)據(jù)的訪問(wèn)模式時(shí),他們可能會(huì)在用戶端進(jìn)行水平分區(qū),而不是在數(shù)據(jù)庫(kù)端,這叫作應(yīng)用程序級(jí)別的分片。
“應(yīng)用程序級(jí)別的分片”通常給人一種錯(cuò)誤的印象,即認(rèn)為分片應(yīng)該存在于應(yīng)用程序中。實(shí)際上,分片功能可以作為數(shù)據(jù)庫(kù)前面的一個(gè)層。隨著數(shù)據(jù)增長(zhǎng)和模式的迭代,分片需求可能會(huì)變得越來(lái)越復(fù)雜。
一個(gè)應(yīng)用服務(wù)器與分片服務(wù)分離的示例架構(gòu)
將分片作為單獨(dú)的服務(wù),可以在不重新部署應(yīng)用程序的前提下提升分片策略的迭代能力。Vitess 是這方面的一個(gè)很好的例子。Vitess 為 MySQL 提供了水平分片能力,客戶端可以通過(guò) MySQL 協(xié)議連接到 Vitess,Vitess 會(huì)在各個(gè) MySQL 節(jié)點(diǎn)上對(duì)數(shù)據(jù)進(jìn)行分片。
https://youtu.be/OCS45iy5v1M?t=204
自動(dòng)遞增是生成主鍵的常用方法。使用數(shù)據(jù)庫(kù)作為 ID 生成器,并在數(shù)據(jù)庫(kù)中創(chuàng)建帶有 ID 生成的表,這種情況并不少見。但是,通過(guò)自動(dòng)遞增生成主鍵可能不是理想的方法,原因如下:
在分布式數(shù)據(jù)庫(kù)系統(tǒng)中,自動(dòng)遞增是一個(gè)難題。你需要一個(gè)全局鎖來(lái)生成 ID,但如果可以生成 UUID,就不需要協(xié)調(diào)數(shù)據(jù)庫(kù)節(jié)點(diǎn)。使用帶鎖的自動(dòng)遞增可能會(huì)引入爭(zhēng)用,并且可能會(huì)顯著降低分布式寫入性能。像 MySQL 這樣的數(shù)據(jù)庫(kù)可能需要特定的配置,并且要保證主主復(fù)制的正確性。但是,配置很容易出錯(cuò),并可能導(dǎo)致寫入中斷。
一些數(shù)據(jù)庫(kù)有基于主鍵的分區(qū)算法。順序 ID 可能會(huì)導(dǎo)致不可預(yù)測(cè)的熱點(diǎn),導(dǎo)致某些分區(qū)數(shù)據(jù)量過(guò)大,而其他分區(qū)處于空閑狀態(tài)。
訪問(wèn)數(shù)據(jù)庫(kù)最快方法是使用主鍵。如果你使用了其他列來(lái)標(biāo)識(shí)記錄,那么順序 ID 可能會(huì)變得毫無(wú)意義。所以,請(qǐng)盡可能選擇一個(gè)全局唯一的自然主鍵 (例如用戶名)。
在決定哪種方法更適合自己之前,請(qǐng)考慮一下自動(dòng)遞增 ID 與 UUID 對(duì)索引、分區(qū)和分片的影響。
多版本并發(fā)控制 (MVCC) 可以支持上述的很多一致性方面的能力。一些數(shù)據(jù)庫(kù) (如 Postgres、Spanner) 借助 MVCC 讓每個(gè)事務(wù)可以查看快照,即數(shù)據(jù)庫(kù)的舊版本。這些事務(wù)可以串行化,以此來(lái)保持一致性。從舊快照讀取數(shù)據(jù)時(shí),讀取的是陳舊的數(shù)據(jù)。
讀取稍微陳舊一點(diǎn)的數(shù)據(jù)也是很有用的,例如,基于數(shù)據(jù)生成分析報(bào)告或計(jì)算近似聚合值。
讀取陳舊數(shù)據(jù)的第一個(gè)好處是延時(shí) (特別是當(dāng)數(shù)據(jù)庫(kù)分布在不同的地理區(qū)域時(shí))。MVCC 數(shù)據(jù)庫(kù)的第二個(gè)優(yōu)點(diǎn)是它允許只讀事務(wù)是無(wú)鎖的。如果讀取陳舊數(shù)據(jù)是可接受的,那么對(duì)于偏重讀取很大的應(yīng)用程序來(lái)說(shuō),這就是一個(gè)主要的優(yōu)點(diǎn)。
應(yīng)用服務(wù)器從本地副本讀取 5 秒前的陳舊數(shù)據(jù),即使在太平洋的另一端有可用的最新版本
數(shù)據(jù)庫(kù)會(huì)自動(dòng)清除舊版本,在某些情況下,它們?cè)试S按需進(jìn)行清理。例如,Postgres 允許用戶按需清理,或者每隔一段時(shí)間自動(dòng)清理一次,而 Spanner 則使用垃圾回收器來(lái)清除超過(guò)一小時(shí)的陳舊數(shù)據(jù)。
計(jì)算系統(tǒng)最隱秘的秘密是所有的時(shí)間 API 都會(huì)“撒謊”。計(jì)算機(jī)無(wú)法準(zhǔn)確地知道當(dāng)前時(shí)間,它們都有一個(gè)石英晶體,會(huì)產(chǎn)生計(jì)時(shí)信號(hào),但石英晶體無(wú)法準(zhǔn)確地計(jì)時(shí),不是比實(shí)際時(shí)鐘快就是比實(shí)際時(shí)鐘慢。每天出現(xiàn)的時(shí)間漂移最多可長(zhǎng)達(dá) 20 秒。為了準(zhǔn)確起見,計(jì)算機(jī)上的時(shí)間需要時(shí)不時(shí)地與實(shí)際時(shí)間同步。
NTP 服務(wù)器用于同步時(shí)間,但同步本身可能會(huì)因?yàn)榫W(wǎng)絡(luò)而出現(xiàn)延遲。在同一個(gè)數(shù)據(jù)中心中進(jìn)行 NTP 服務(wù)器同步需要花費(fèi)一點(diǎn)時(shí)間,而與公共 NTP 服務(wù)器同步有可能出現(xiàn)更大的傾斜。
原子時(shí)鐘和 GPS 時(shí)鐘是用來(lái)確定當(dāng)前時(shí)間更好的一種來(lái)源,但它們昂貴,而且需要復(fù)雜的設(shè)置,無(wú)法在每臺(tái)機(jī)器上安裝??紤]到這些限制,數(shù)據(jù)中心使用了多層方法。雖然原子時(shí)鐘和 GPS 時(shí)鐘提供了準(zhǔn)確的時(shí)間,但它們的時(shí)間是通過(guò)輔助服務(wù)器廣播到其他的機(jī)器上的。這意味著每臺(tái)機(jī)器都會(huì)與實(shí)際的時(shí)間發(fā)生某種量級(jí)的傾斜。
應(yīng)用程序和數(shù)據(jù)庫(kù)通常位于不同的機(jī)器上,不僅分布在多臺(tái)機(jī)器上的數(shù)據(jù)庫(kù)節(jié)點(diǎn)無(wú)法就時(shí)間達(dá)成一致,應(yīng)用服務(wù)器時(shí)鐘和數(shù)據(jù)庫(kù)節(jié)點(diǎn)時(shí)鐘也無(wú)法達(dá)成一致。
谷歌的 TrueTime 采用了不同的方法。大多數(shù)人認(rèn)為谷歌在時(shí)鐘方面的進(jìn)步要?dú)w功于他們使用了原子時(shí)鐘和 GPS 時(shí)鐘,但這只是其中的部分原因。TrueTime 實(shí)際上做了這些事情:
TrueTime 使用兩種不同的來(lái)源:GPS 和原子時(shí)鐘。這些時(shí)鐘有不同的故障模式,因此同時(shí)使用它們提高了可靠性。
TrueTime 有一個(gè)非常規(guī)的 API,它以間隔的形式返回時(shí)間,時(shí)間可以是下限和上限之間的任意點(diǎn)。谷歌的分布式數(shù)據(jù)庫(kù) Spanner 可以等待,直到確定當(dāng)前時(shí)間超過(guò)了特定時(shí)間。
Spanner 組件使用了 TrueTime,TT.now() 返回一個(gè)時(shí)間間隔,Spanner 可以進(jìn)行 sleep,以確保當(dāng)前時(shí)間已經(jīng)通過(guò)了一個(gè)特定的時(shí)間戳。
如果你在一個(gè)房間里問(wèn) 10 個(gè)人“延遲”是什么意思,他們可能會(huì)有不同的答案。在數(shù)據(jù)庫(kù)中,延遲通常是指“數(shù)據(jù)庫(kù)延遲”,而不是客戶端所感知到的延遲??蛻舳丝梢钥吹綌?shù)據(jù)庫(kù)的延遲和網(wǎng)絡(luò)延遲。在調(diào)試問(wèn)題時(shí),能夠識(shí)別客戶端延遲和數(shù)據(jù)庫(kù)延遲是非常重要的。在收集和顯示指標(biāo)時(shí),始終都要考慮到兩者。
有時(shí)候,數(shù)據(jù)庫(kù)會(huì)說(shuō)明它們?cè)谧x寫吞吐量和延遲方面的性能特征和限制。但在評(píng)估數(shù)據(jù)庫(kù)性能時(shí),更全面的做法是對(duì)每一個(gè)關(guān)鍵操作 (查詢或事務(wù)) 進(jìn)行評(píng)估。例如:
往一張表 X(已經(jīng)有 5 千萬(wàn)行記錄)插入新行,并更新相關(guān)表,此時(shí)的寫入吞吐量和延遲是怎么樣的?
當(dāng)平均朋友數(shù)量為 500 人時(shí),查詢某個(gè)用戶的朋友的朋友,此時(shí)的延遲是怎樣的?
當(dāng)用戶訂閱了 500 個(gè)帳號(hào) (每小時(shí)有 X 項(xiàng)更新) 時(shí),查詢用戶時(shí)間軸的前 100 條記錄,此時(shí)的延遲是怎樣的?
性能評(píng)估可能包含了這些情況,直到你確信數(shù)據(jù)庫(kù)能夠滿足你的性能需求為止。
在收集指標(biāo)時(shí),要小心高基數(shù)。如果你需要高基數(shù)調(diào)試數(shù)據(jù),請(qǐng)使用日志,甚至是分布式跟蹤信息。
并不是每一種數(shù)據(jù)庫(kù)都支持嵌套事務(wù)。嵌套事務(wù)可能會(huì)導(dǎo)致意外的編程錯(cuò)誤,這些錯(cuò)誤不容易識(shí)別,直到拋出異常。
嵌套事務(wù)可以在客戶端檢測(cè)和避免。如果無(wú)法避免,就要注意避免出現(xiàn)意外情況,即已提交的事務(wù)由于子事務(wù)而意外中止。
在不同的層封裝事務(wù)可能會(huì)出現(xiàn)意外的嵌套事務(wù),而從可讀性角度來(lái)看,可能很難理解其意圖??纯聪旅孢@個(gè)例子:
with newTransaction(): Accounts.create("609-543-222") with newTransaction(): Accounts.create("775-988-322") throw Rollback();
這段代碼的結(jié)果是什么?它是回滾兩個(gè)事務(wù)還是只回滾內(nèi)部事務(wù)?如果我們使用多層庫(kù)來(lái)封裝事務(wù),會(huì)發(fā)生什么呢?我們是否能夠識(shí)別并改善這種情況?
假設(shè)一個(gè)數(shù)據(jù)層已經(jīng)在一個(gè)事務(wù)中實(shí)現(xiàn)了多個(gè)操作 (例如 newAccount),在業(yè)務(wù)邏輯的事務(wù)中運(yùn)行它們時(shí)會(huì)發(fā)生什么?此時(shí)具有怎樣的隔離性和一致性特征?
function newAccount(id string) { with newTransaction(): Accounts.create(id) }
與其要處理這種問(wèn)題,不如避免使用嵌套事務(wù)。數(shù)據(jù)層仍然可以實(shí)現(xiàn)自己的操作,但無(wú)需創(chuàng)建事務(wù)。然后,業(yè)務(wù)邏輯可以啟動(dòng)、執(zhí)行、提交或中止事務(wù)。
function newAccount(id string) { Accounts.create(id) } // 在主程序中: with newTransaction(): // 從數(shù)據(jù)庫(kù)讀取一些配置數(shù)據(jù) // 調(diào)用ID服務(wù)生成ID Accounts.create(id) Uploads.create(id) // 創(chuàng)建用戶上傳隊(duì)列
應(yīng)用程序開發(fā)人員可能會(huì)在事務(wù)中使用應(yīng)用程序狀態(tài)來(lái)更新某些值或設(shè)置查詢參數(shù),這個(gè)時(shí)候要注意作用域。當(dāng)發(fā)生網(wǎng)絡(luò)問(wèn)題時(shí),客戶端經(jīng)常會(huì)重試事務(wù)。如果事務(wù)依賴的狀態(tài)在其他地方被修改,就使用了錯(cuò)誤的值。
var seq int64 with newTransaction(): newSeq := atomic.Increment(&seq) Entries.query(newSeq) // 其他操作
無(wú)論最終結(jié)果如何,上面的事務(wù)每次運(yùn)行時(shí)都會(huì)增加序列號(hào)。如果由于網(wǎng)絡(luò)原因提交失敗,在第二次重試時(shí),它將使用不同的序列號(hào)進(jìn)行查詢。
查詢計(jì)劃決定了數(shù)據(jù)庫(kù)將會(huì)如何執(zhí)行查詢。它們還會(huì)在執(zhí)行查詢之前對(duì)其進(jìn)行分析和優(yōu)化。查詢計(jì)劃只能根據(jù)某些信號(hào)提供一些可能的估計(jì)。例如下面這個(gè)查詢:
SELECT * FROM articles where author = "rakyll" order by title;
獲取結(jié)果有兩種方法:
全表掃描:我們可以遍歷表中的每條記錄,并返回與作者姓名匹配的文章,然后根據(jù)標(biāo)題排序。
索引掃描:我們可以使用一個(gè)索引來(lái)查找匹配的 ID,獲取這些行,然后排序。
查詢計(jì)劃的作用是確定最佳執(zhí)行策略。但可用于預(yù)測(cè)的信號(hào)是有限的,因此可能會(huì)導(dǎo)致做出錯(cuò)誤的決策。DBA 或開發(fā)人員可以用它們來(lái)診斷和調(diào)優(yōu)性能較差的查詢。慢查詢?nèi)罩?、延遲問(wèn)題或執(zhí)行時(shí)間統(tǒng)計(jì)信息可用于識(shí)別需要優(yōu)化的查詢。
查詢計(jì)劃提供的一些度量可能不會(huì)很準(zhǔn)確,特別是在估計(jì)延遲或 CPU 時(shí)間方面。作為查詢計(jì)劃的補(bǔ)充,跟蹤和執(zhí)行路徑工具在診斷這些問(wèn)題方面更有用,但并不是每種數(shù)據(jù)庫(kù)都會(huì)提供這些工具。
在線或?qū)崟r(shí)遷移就是在不停機(jī)、不影響數(shù)據(jù)正確性的情況下從一個(gè)數(shù)據(jù)庫(kù)遷移到另一個(gè)數(shù)據(jù)庫(kù)。如果要遷移到同一個(gè)數(shù)據(jù)庫(kù)或引擎,實(shí)時(shí)遷移會(huì)容易一些,但要遷移到具有不同性能特征和模式需求的新數(shù)據(jù)庫(kù),就要復(fù)雜得多。
在線遷移有一些可遵循的模式:
在兩個(gè)數(shù)據(jù)庫(kù)上執(zhí)行雙重寫操作。在這個(gè)階段,新的數(shù)據(jù)庫(kù)不包含所有數(shù)據(jù),但會(huì)包含新數(shù)據(jù)。在這一步穩(wěn)妥之后,就可以進(jìn)入第二步。啟用針對(duì)兩個(gè)數(shù)據(jù)庫(kù)的查詢路徑。
讓新數(shù)據(jù)庫(kù)承擔(dān)主要的讀寫任務(wù)。
停止對(duì)舊數(shù)據(jù)庫(kù)的寫入,但可以繼續(xù)從舊數(shù)據(jù)庫(kù)讀取數(shù)據(jù)。此時(shí),新數(shù)據(jù)庫(kù)仍然不包含所有數(shù)據(jù),要讀取舊數(shù)據(jù),仍然需要從舊數(shù)據(jù)庫(kù)獲得。
此時(shí),舊數(shù)據(jù)庫(kù)是只讀的。用舊數(shù)據(jù)庫(kù)中的數(shù)據(jù)填充新數(shù)據(jù)庫(kù)缺失的數(shù)據(jù)。遷移完成后,所有讀寫路徑都可以使用新數(shù)據(jù)庫(kù),舊數(shù)據(jù)庫(kù)可以從系統(tǒng)中移除。
數(shù)據(jù)庫(kù)的增長(zhǎng)會(huì)帶來(lái)不可預(yù)測(cè)的伸縮性問(wèn)題。
隨著數(shù)據(jù)庫(kù)的增長(zhǎng),之前對(duì)數(shù)據(jù)大小和網(wǎng)絡(luò)容量的假設(shè)或預(yù)期可能會(huì)過(guò)時(shí),比如大型 scheme 重構(gòu)、大規(guī)模的運(yùn)維改進(jìn)、容量問(wèn)題、部署計(jì)劃改變或遷移到其他數(shù)據(jù)庫(kù)以避免宕機(jī)。
不要以為了解數(shù)據(jù)庫(kù)的內(nèi)部結(jié)構(gòu)就足夠了,因?yàn)樯炜s性會(huì)帶來(lái)新的未知問(wèn)題。不可預(yù)測(cè)的數(shù)據(jù)熱點(diǎn)、不均勻的數(shù)據(jù)分布、意外的容量和硬件問(wèn)題、不斷增長(zhǎng)的流量和新的網(wǎng)絡(luò)分區(qū),這些都會(huì)迫使你重新考慮數(shù)據(jù)庫(kù)、數(shù)據(jù)模型、部署模型和部署規(guī)模。
關(guān)于數(shù)據(jù)庫(kù)知識(shí)都有哪些就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
當(dāng)前題目:數(shù)據(jù)庫(kù)知識(shí)都有哪些
網(wǎng)站URL:http://www.rwnh.cn/article10/jieddo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、品牌網(wǎng)站制作、企業(yè)建站、建站公司、搜索引擎優(yōu)化、網(wǎng)站內(nèi)鏈
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)