58 mysql實(shí)戰(zhàn)45講45 自增id用完怎么辦_h_第1頁
58 mysql實(shí)戰(zhàn)45講45 自增id用完怎么辦_h_第2頁
58 mysql實(shí)戰(zhàn)45講45 自增id用完怎么辦_h_第3頁
58 mysql實(shí)戰(zhàn)45講45 自增id用完怎么辦_h_第4頁
58 mysql實(shí)戰(zhàn)45講45 自增id用完怎么辦_h_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、45 | id用完怎么辦? 自增2019-02-25 林曉斌 MySQL里有很多自增的id,每個(gè)自增id都是定義了初始值,然后不停地往上加步長。雖然自然數(shù) 是沒有上限的,但是在計(jì)算機(jī)里,只要定義了表示這個(gè)數(shù)的字節(jié)長度,那它就有上限。比如,無符號(hào)整型(unsigned int)是4個(gè)字節(jié),上限就是232-1。 既然自增id有上限,就有可能被用完。但是,自增id用完了會(huì)怎么樣呢? 今天這篇文章,我們就來看看MySQL里面的幾種自增id,一起分析一下它們的值達(dá)到上限以后, 會(huì)出現(xiàn)什么情況。 表定義自增值id 說到自增id,你第一個(gè)想到的應(yīng)該就是表結(jié)構(gòu)定義里的自增字段,也就是我在第39篇文章自增 主鍵

2、為什么不是連續(xù)的?中和你介紹過的自增主鍵id。 表定義的自增值達(dá)到上限后的邏輯是:再申請(qǐng)下一個(gè)id時(shí),得到的值保持不變。 我們可以通過下面這個(gè)語句序列驗(yàn)證一下: 可以看到,第一個(gè)ert語句插入數(shù)據(jù)成功后,這個(gè)表的AUTO_INCREMENT沒有改變(還是 4294967295),就導(dǎo)致了第二個(gè)鍵沖突錯(cuò)誤。 ert語句又拿到相同的自增id值,再試圖執(zhí)行插入語句,報(bào)主232-1(4294967295)不是一個(gè)特別大的數(shù),對(duì)于一個(gè)頻繁插入刪除數(shù)據(jù)的表來說,是可能會(huì)被 用完的。因此在建表的時(shí)候你需要考察你的表是否有可能達(dá)到這個(gè)上限,如果有可能,就應(yīng)該創(chuàng)建成8個(gè)字節(jié)的bigint unsigned。 I

3、nnoDB系統(tǒng)自增row id 如果你創(chuàng)建的InnoDB表沒有指定主鍵,那么InnoDB會(huì)給你創(chuàng)建一個(gè)不可見的,長度為6個(gè)字節(jié)的row_id。InnoDB維護(hù)了一個(gè)全局的dict_sys.row_id值,所有無主鍵的InnoDB表,每插入一行數(shù)據(jù),都將當(dāng)前的dict_sys.row_id值作為要插入數(shù)據(jù)的row_id,然后把dict_sys.row_id的值加1。 實(shí)際上,在代碼實(shí)現(xiàn)時(shí)row_id是一個(gè)長度為8字節(jié)的無符號(hào)長整型(bigint unsigned)。但是,InnoDB在設(shè)計(jì)時(shí),給row_id留的只是6個(gè)字節(jié)的長度,這樣寫到數(shù)據(jù)表中時(shí)只放了最后6個(gè) 字節(jié),所以row_id能寫到數(shù)據(jù)

4、表中的值,就有兩個(gè)特征: 1. row_id寫入表中的值范圍,是從0到248-1; 2. 當(dāng)dict_sys.row_id=248時(shí),如果再有插入數(shù)據(jù)的行為要來申請(qǐng)row_id,拿到以后再取最后6個(gè) 字節(jié)的話就是0。 也就是說,寫入表的row_id是從0開始到248-1。達(dá)到上限后,下一個(gè)值就是0,然后繼續(xù)循環(huán)。 當(dāng)然,248-1這個(gè)值本身已經(jīng)很大了,但是如果一個(gè)MySQL實(shí)例跑得足夠久的話,還是可能達(dá)到這個(gè)上限的。在InnoDB邏輯里,申請(qǐng)到row_id=N后,就將這行數(shù)據(jù)寫入表中;如果表中已經(jīng)存 create table t(id int unsigned auto_increment p

5、rimary key) auto_increment=4294967295; ert into t values(null);/成功插入一行 4294967295 show create table t;/* CREATE TABLE t (id int(10) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (id) ENGINE=InnoDB AUTO_INCREMENT=4294967295;*/ert into t values(null);/Duplicate entry 4294967295 for key PRIMARY在row_id=

6、N的行,新寫入的行就會(huì)覆蓋原有的行。 要驗(yàn)證這個(gè)結(jié)論的話,你可以通過gdb修改系統(tǒng)的自增row_id來實(shí)現(xiàn)。注意,用gdb改變量這個(gè) 操作是為了便于我們復(fù)現(xiàn)問題,只能在測(cè)試環(huán)境使用。 圖1 row_id用完的驗(yàn)證序列圖2 row_id用完的效果驗(yàn)證 可以看到,在我用gdb將dict_sys.row_id設(shè)置為248之后,再插入的a=2的行會(huì)出現(xiàn)在表t的第一行,因?yàn)檫@個(gè)值的row_id=0。之后再插入的a=3的行,由于row_id=1,就覆蓋了之前a=1的行, 因?yàn)閍=1這一行的row_id也是1。 從這個(gè)角度看,我們還是應(yīng)該在InnoDB表中主動(dòng)創(chuàng)建自增主鍵。因?yàn)椋碜栽鰅d到達(dá)上限后, 再插

7、入數(shù)據(jù)時(shí)報(bào)主鍵沖突錯(cuò)誤,是更能被接受的。 畢竟覆蓋數(shù)據(jù),就意味著數(shù)據(jù)丟失,影響的是數(shù)據(jù)可靠性;報(bào)主鍵沖突,是插入失敗,影響的是可用性。而一般情況下,可靠性優(yōu)先于可用性。 Xid在第15篇文章答疑文章(一):日志和索引相關(guān)問題中,我和你介紹redo log和binlog相配 合的時(shí)候,提到了它們有一個(gè)共同的字段叫作Xid。它在MySQL中是用來對(duì)應(yīng)事務(wù)的。 那么,Xid在MySQL內(nèi)部是怎么生成的呢? MySQL內(nèi)部維護(hù)了一個(gè)全局變量global_query_id,每次執(zhí)行語句的時(shí)候?qū)⑺x值給Query_id, 然后給這個(gè)變量加1。如果當(dāng)前語句是這個(gè)事務(wù)執(zhí)行的第一條語句,那么MySQL還會(huì)同時(shí)把

8、 Query_id賦值給這個(gè)事務(wù)的Xid。 而global_query_id是一個(gè)純內(nèi)存變量,重啟之后就清零了。所以你就知道了,在同一個(gè)數(shù)據(jù)庫實(shí) 例中,不同事務(wù)的Xid也是有可能相同的。 但是MySQL重啟之后會(huì)重新生成新的binlog文件,這就保證了,同一個(gè)binlog文件里,Xid一定是 惟一的。 雖然MySQL重啟不會(huì)導(dǎo)致同一個(gè)binlog里面出現(xiàn)兩個(gè)相同的Xid,但是如果global_query_id達(dá)到上限后,就會(huì)繼續(xù)從0開始計(jì)數(shù)。從理論上講,還是就會(huì)出現(xiàn)同一個(gè)binlog里面出現(xiàn)相同Xid的場 景。 因?yàn)間lobal_query_id定義的長度是8個(gè)字節(jié),這個(gè)自增值的上限是264-

9、1。要出現(xiàn)這種情況,必須 是下面這樣的過程: 1. 執(zhí)行一個(gè)事務(wù),假設(shè)Xid是A; 2. 接下來執(zhí)行264次查詢語句,讓global_query_id回到A; 3. 再啟動(dòng)一個(gè)事務(wù),這個(gè)事務(wù)的Xid也是A。 不過,264這個(gè)值太大了,大到你可以認(rèn)為這個(gè)可能性只會(huì)存在于理論上。 Innodb trx id Xid和InnoDB的trx_id是兩個(gè)容易混淆的概念。 Xid是由server層維護(hù)的。InnoDB內(nèi)部使用Xid,就是為了能夠在InnoDB事務(wù)和server之間做關(guān) 聯(lián)。但是,InnoDB自己的trx_id,是另外維護(hù)的。 其實(shí),你應(yīng)該非常熟悉這個(gè)trx_id。它就是在我們?cè)诘?篇文章事

10、務(wù)到底是隔離的還是不隔離 的?中講事務(wù)可見性時(shí),用到的事務(wù)id(transaction id)。 InnoDB內(nèi)部維護(hù)了一個(gè)max_trx_id全局變量,每次需要申請(qǐng)一個(gè)新的trx_id時(shí),就獲得 max_trx_id的當(dāng)前值,然后并將max_trx_id加1。 InnoDB數(shù)據(jù)可見性的核心思想是:每一行數(shù)據(jù)都記錄了更新它的trx_id,當(dāng)一個(gè)事務(wù)讀到一行數(shù) 據(jù)的時(shí)候,判斷這個(gè)數(shù)據(jù)是否可見的方法,就是通過事務(wù)的一致性視圖與這行數(shù)據(jù)的trx_id做對(duì) 比。 對(duì)于正在執(zhí)行的事務(wù),你可以從information_schema.innodb_trx表中看到事務(wù)的trx_id。我在上一篇文章的末尾留給你

11、的思考題,就是關(guān)于從innodb_trx表里面查到的trx_id的。現(xiàn)在,我 們一起來看一個(gè)事務(wù)現(xiàn)場: 圖3 事務(wù)的trx_id session B里,我從innodb_trx表里查出的這兩個(gè)字段,第二個(gè)字段trx_mysql_thread_id就是線程id。顯示線程id,是為了說明這兩次查詢看到的事務(wù)對(duì)應(yīng)的線程id都是5,也就是session A所在的線程。 可以看到,T2時(shí)刻顯示的trx_id是一個(gè)很大的數(shù);T4時(shí)刻顯示的trx_id是1289,看上去是一個(gè)比 較正常的數(shù)字。這是什么原因呢? 實(shí)際上,在T1時(shí)刻,session A還沒有涉及到更新,是一個(gè)只讀事務(wù)。而對(duì)于只讀事務(wù),InnoD

12、B 并不會(huì)分配trx_id。也就是說: 1. 在T1時(shí)刻,trx_id的值其實(shí)就是0。而這個(gè)很大的數(shù),只是顯示用的。一會(huì)兒我會(huì)再和你說說 這個(gè)數(shù)據(jù)的生成邏輯。2. 直到session A 在T3時(shí)刻執(zhí)行ert語句的時(shí)候,InnoDB才真正分配了trx_id。所以,T4時(shí) 刻,session B查到的這個(gè)trx_id的值就是1289。 需要注意的是,除了顯而易見的修改類語句外,如果在select 語句后面加上for update,這個(gè)事 務(wù)也不是只讀事務(wù)。 在上一篇文章的評(píng)論區(qū),有同學(xué)提出,實(shí)驗(yàn)的時(shí)候發(fā)現(xiàn)不止加1。這是因?yàn)椋?1. update 和 delete語句除了事務(wù)本身,還涉及到標(biāo)記刪除

13、舊數(shù)據(jù),也就是要把數(shù)據(jù)放到purge 隊(duì)列里等待后續(xù)物理刪除,這個(gè)操作也會(huì)把max_trx_id+1, 因此在一個(gè)事務(wù)中至少加2; 2. InnoDB的操作,比如表的索引信息統(tǒng)計(jì)這類操作,也是會(huì)啟動(dòng)內(nèi)部事務(wù)的,因此你可 能看到,trx_id值并不是按照加1遞增的。 那么,T2時(shí)刻查到的這個(gè)很大的數(shù)字是怎么來的呢?其實(shí),這個(gè)數(shù)字是每次查詢的時(shí)候由系統(tǒng)臨時(shí)計(jì)算出來的。它的算法是:把當(dāng)前事務(wù)的trx變量的 指針地址轉(zhuǎn)成整數(shù),再加上248。使用這個(gè)算法,就可以保證以下兩點(diǎn): 1. 因?yàn)橥粋€(gè)只讀事務(wù)在執(zhí)行期間,它的指針地址是不會(huì)變的,所以不論是在 innodb_trx還是 在innodb_locks表

14、里,同一個(gè)只讀事務(wù)查出來的trx_id就會(huì)是一樣的。 2. 如果有并行的多個(gè)只讀事務(wù),每個(gè)事務(wù)的trx變量的指針地址肯定不同。這樣,不同的并發(fā)只讀事務(wù),查出來的trx_id就是不同的。 那么,為什么還要再加上248呢? 在顯示值里面加上248,目的是要保證只讀事務(wù)顯示的trx_id值比較大,正常情況下就會(huì)區(qū)別于讀 寫事務(wù)的id。但是,trx_id跟row_id的邏輯類似,定義長度也是8個(gè)字節(jié)。因此,在理論上還是可 能出現(xiàn)一個(gè)讀寫事務(wù)與一個(gè)只讀事務(wù)顯示的trx_id相同的情況。不過這個(gè)概率很低,并且也沒有 什么實(shí)質(zhì),可以不管它。 另一個(gè)問題是,只讀事務(wù)不分配trx_id,有什么好處呢?一個(gè)好處是

15、,這樣做可以減小事務(wù)視圖里面活躍事務(wù)數(shù)組的大小。因?yàn)楫?dāng)前正在運(yùn)行的只讀事務(wù),是不影響數(shù)據(jù)的可見性判斷的。所以,在創(chuàng)建事務(wù)的一致性視圖時(shí),InnoDB就只需要 拷貝讀寫事務(wù)的trx_id。 另一個(gè)好處是,可以減少trx_id的申請(qǐng)次數(shù)。在InnoDB里,即使你只是執(zhí)行一個(gè)普通的select 語句,在執(zhí)行過程中,也是要對(duì)應(yīng)一個(gè)只讀事務(wù)的。所以只讀事務(wù)優(yōu)化后,普通的查詢語句 不需要申請(qǐng)trx_id,就大大減少了并發(fā)事務(wù)申請(qǐng)trx_id的鎖沖突。 由于只讀事務(wù)不分配trx_id,一個(gè)自然而然的結(jié)果就是trx_id的增加速度變慢了。 但是,max_trx_id會(huì)持久化存儲(chǔ),重啟也不會(huì)重置為0,那么從理論

16、上講,只要一個(gè)MySQL服務(wù) 跑得足夠久,就可能出現(xiàn)max_trx_id達(dá)到248-1的上限,然后從0開始的情況。 當(dāng)達(dá)到這個(gè)狀態(tài)后,MySQL就會(huì)持續(xù)出現(xiàn)一個(gè)臟讀的bug,我們來復(fù)現(xiàn)一下這個(gè)bug。 首先我們需要把當(dāng)前的max_trx_id先修改成248-1。注意:這個(gè)case里使用的是可重復(fù)讀隔離級(jí) 別。具體的操作流程如下: 圖 4 復(fù)現(xiàn)臟讀 由于我們已經(jīng)把系統(tǒng)的max_trx_id設(shè)置成了248-1,所以在session A啟動(dòng)的事務(wù)TA的低水位就是 248-1。在T2時(shí)刻,session B執(zhí)行第一條update語句的事務(wù)id就是248-1,而第二條update語句的事務(wù)id 就是0了

17、,這條update語句執(zhí)行后生成的數(shù)據(jù)版本上的trx_id就是0。 在T3時(shí)刻,session A執(zhí)行select語句的時(shí)候,判斷可見性發(fā)現(xiàn),c=3這個(gè)數(shù)據(jù)版本的trx_id,小于 事務(wù)TA的低水位,因此認(rèn)為這個(gè)數(shù)據(jù)可見。 但,這個(gè)是臟讀。由于低水位值會(huì)持續(xù)增加,而事務(wù)id從0開始計(jì)數(shù),就導(dǎo)致了系統(tǒng)在這個(gè)時(shí)刻之后,所有的查詢 都會(huì)出現(xiàn)臟讀的。 并且,MySQL重啟時(shí)max_trx_id也不會(huì)清0,也就是說重啟MySQL,這個(gè)bug仍然存在。 那么,這個(gè)bug也是只存在于理論上嗎?假設(shè)一個(gè)MySQL實(shí)例的TPS是每秒50萬,持續(xù)這個(gè)壓力的話,在17.8年后,就會(huì)出現(xiàn)這個(gè)情況。如果TPS更高,這個(gè)

18、年限自然也就更短了。但是,從MySQL的真正開始流行到現(xiàn)在,恐怕 都還沒有實(shí)例跑到過這個(gè)上限。不過,這個(gè)bug是只要MySQL實(shí)例服務(wù)時(shí)間夠長,就會(huì)必然出現(xiàn) 的。 當(dāng)然,這個(gè)例子更現(xiàn)實(shí)的意義是,可以加深我們對(duì)低水位和數(shù)據(jù)可見性的理解。你也可以借此機(jī)會(huì)再回顧下第8篇文章事務(wù)到底是隔離的還是不隔離的?中的相關(guān)內(nèi)容。 thread id 接下來,我們?cè)倏纯淳€程id(thread_id)。其實(shí),線程id才是MySQL中最常見的一種自增id。平時(shí) 我們?cè)诓楦鞣N現(xiàn)場的時(shí)候,show processlist里面的第一列,就是thread_id。 thread_id的邏輯很好理解:系統(tǒng)保存了一個(gè)全局變量thr

19、ead_id_counter,每新建一個(gè)連接,就 將thread_id_counter賦值給這個(gè)新連接的線程變量。 thread_id_counter定義的大小是4個(gè)字節(jié),因此達(dá)到232-1后,它就會(huì)重置為0,然后繼續(xù)增加。 但是,你不會(huì)在show processlist里看到兩個(gè)相同的thread_id。 這,是因?yàn)镸ySQL設(shè)計(jì)了一個(gè)唯一數(shù)組的邏輯,給新線程分配thread_id的時(shí)候,邏輯代碼是這 樣的: do new_id= thread_id_counter+; while (!thread_ids.ert_unique(new_id).second); 這個(gè)代碼邏輯簡單而且實(shí)現(xiàn)優(yōu)雅

20、,相信你一看就能明白。小結(jié) 今天這篇文章,我給你介紹了MySQL不同的自增id達(dá)到上限以后的行為。數(shù)據(jù)庫系統(tǒng)作為一個(gè)可能需要7*24小時(shí)全年無休的服務(wù),考慮這些邊界是非常有必要的。 每種自增id有各自的應(yīng)用場景,在達(dá)到上限后的表現(xiàn)也不同: 1. 表的自增id達(dá)到上限后,再申請(qǐng)時(shí)它的值就不會(huì)改變,進(jìn)而導(dǎo)致繼續(xù)插入數(shù)據(jù)時(shí)報(bào)主鍵沖突 的錯(cuò)誤。 2. row_id達(dá)到上限后,則會(huì)歸0再重新遞增,如果出現(xiàn)相同的row_id,后寫的數(shù)據(jù)會(huì)覆蓋之前 的數(shù)據(jù)。 3. Xid只需要不在同一個(gè)binlog文件中出現(xiàn)重復(fù)值即可。雖然理論上會(huì)出現(xiàn)重復(fù)值,但是概率極 小,可以忽略不計(jì)。 4. InnoDB的max_tr

21、x_id 遞增值每次MySQL重啟都會(huì)被保存起來,所以我們文章中提到的臟讀 的例子就是一個(gè)必現(xiàn)的bug,好在留給我們的時(shí)間還很充裕。 5. thread_id是我們使用中最常見的,而且也是處理得最好的一個(gè)自增id邏輯了。 當(dāng)然,在MySQL里還有別的自增id,比如table_id、binlog文件序號(hào)等,就留給你去驗(yàn)證和探索 了。 不同的自增id有不同的上限值,上限值的大小取決于聲明的類型長度。而我們專欄聲明的上限id 就是45,所以今天這篇文章也是我們的最后一篇技術(shù)文章了。 既然沒有下一個(gè)id了,課后也就沒有思考題了。今天,我們換一個(gè)輕松的話題,請(qǐng)你來說說,讀 完專欄以后有什么感想吧。 這個(gè)

22、“感想”,既可以是你讀完專欄前后對(duì)某一些知識(shí)點(diǎn)的理解發(fā)生的變化,也可以是你積累的學(xué) 習(xí)專欄文章的好方法,當(dāng)然也可以是吐槽或者對(duì)未來的期望。 歡迎你給我留言,我們?cè)谠u(píng)論區(qū)見,也歡迎你把這篇文章分享給更多的朋友一起閱讀。 精選留言 Continue 跟著學(xué)了三個(gè)多月,受益匪淺,學(xué)到了很多新的知識(shí)和其中的原理! 2019 02 2512作者回復(fù)早 2019 02 25 7克勞德本人服務(wù)端工程師,在學(xué)習(xí)這門課之前數(shù)據(jù)庫一直是我的短板,曾聽朋友說MySQL或數(shù)據(jù)庫中涉及了很多方面的知識(shí)點(diǎn),每一個(gè)拿出來展開講幾乎都能出一本書了,對(duì)數(shù)據(jù)庫是越來越忌憚 ,同時(shí)也因?yàn)楣ぷ魃喜]有過多接觸,水平便一直停留在編寫簡

23、單SQL層面。 在面試中被問到數(shù)據(jù)庫問題,只能無奈的說這塊不太清楚,也曾在網(wǎng)上自學(xué)過,但網(wǎng)上的文章知識(shí)點(diǎn)比較零散,很多都是給出一些結(jié)論性的觀點(diǎn),由于不了解其內(nèi)部原理,記憶很難深刻。老實(shí)說,當(dāng)初報(bào)這門課的時(shí)候就像買技術(shù)書籍一樣,我相信大家都有這樣的體會(huì),以為買到了就等于學(xué)到了,所以有一段時(shí)間沒有點(diǎn)開看過,以至于后面開始學(xué)的時(shí)候都是在追趕老師和大家的進(jìn)度,唯一遺憾的地方就是沒能跟老師及時(shí)留言互動(dòng)。 這門課雖然是文字授課,但字里行間給我的感覺就是很親切很舒服,為什么呢,因?yàn)槔蠋熆梢园鸦逎闹R(shí)變得通俗易懂,有時(shí)我在思考,如果讓我來講一個(gè)自己擅長的領(lǐng)域是否也能做到這一點(diǎn),如果要做到的話需要什么樣的知識(shí)

24、儲(chǔ)備呢。 最后真要感謝老師的這門課,讓我從心里不再懼怕數(shù)據(jù)庫問題,不管是工作還是面試中信心倍增,現(xiàn)在時(shí)不時(shí)都敢和我們DBA“切磋切磋“了,哈哈。 祝好 2019 02 25 作者回復(fù) “切磋切磋“ 留言不會(huì)“過時(shí)”哈,在對(duì)應(yīng)的章節(jié)下面提出相關(guān)的問題,我會(huì)持續(xù)關(guān)注評(píng)論區(qū) 2019 02 25 3三胖老師,我才學(xué)了四分之一的課程,但是這門課已經(jīng)更新完了,我是直接跑到最后一節(jié)技術(shù)篇來留言的!很想知道,后來者比如我在學(xué)到后面的課程時(shí)遇到問題留言,老師還會(huì)看會(huì)回復(fù)嗎? (老師的課程超值!) 2019 02 25作者回復(fù) 會(huì)看的 系統(tǒng)是按照留言時(shí)間顯示的 而且我在這事情上有強(qiáng)迫癥,一定會(huì)讓“未處理問題”變

25、成0的 只是說如果是其他同學(xué)評(píng)論區(qū)問過的問題,我可能就不會(huì)重復(fù)回復(fù)了 2019 02 25 2某、人 很遺憾沒能堅(jiān)持到最后,但是也很慶幸能遇到這么好的專欄。以前了解mysql都是一些零散的知識(shí)點(diǎn),通過學(xué)習(xí)完專欄,不論是mysql整體架構(gòu)還是基礎(chǔ)的知識(shí)點(diǎn),都有了更深的認(rèn)識(shí)。以后就把老 師的文檔 方文檔查,出現(xiàn)問題先來看看專欄。 感觸特別深的是,老師對(duì)于提到的每一個(gè)問題,都會(huì)嚴(yán)謹(jǐn)又認(rèn)真的去回答,盡量幫助每一位同學(xué)都 能有所收獲。要做到這一點(diǎn),是特別耗費(fèi)精力的。 感謝老師的傳道授業(yè)解惑,希望以后有機(jī)會(huì)能當(dāng)面向老師請(qǐng)教問題。期待老師下一部杰作 2019 02 26 作者回復(fù) 剛過完年都是很忙的, 找時(shí)

26、間補(bǔ)上哈,等你的評(píng)論區(qū)留言_2019 02 26 2夜空中最亮的星(華仔) 不知道是最后一篇,否則的話就慢些讀完了; 我是一名運(yùn)維,公司也沒有DBA,所以MySQL庫也歸我收拾; 讀了老師的專欄,操作起數(shù)據(jù)庫來,心情更好了; 老師的課,讓我有了想看完高性能MySQL的興趣; 聽了老師的課,開發(fā)都來問我數(shù)據(jù)庫的問題了,高興; 老師你會(huì)有返場嗎?我猜會(huì) 可否透漏下接下來的安排,會(huì)有續(xù)集嗎?進(jìn)階嗎? 不想這一別就是一生。 您的從未謀面的學(xué)生。 2019 02 25作者回復(fù) 謝謝你 “開發(fā)都來問我數(shù)據(jù)庫的問題了”,當(dāng)年我也是這么開始“入坑”,加油 2019 02 25 2極客時(shí)間通過這個(gè)專欄的系統(tǒng)學(xué)習(xí)

27、,梳理很多知識(shí)點(diǎn)、擴(kuò)展了我對(duì)MySQL的認(rèn)識(shí)及以後使用。感謝老師 的諄諄教導(dǎo)! 2019 02 251NoDBA 低版本thread_id超過232-1后,在general log顯示是負(fù)數(shù),高版本貌似沒有這個(gè)問題,是否高版本的thread_id是8字節(jié)呢? 2019 02 27 作者回復(fù) 主要不是定義的問題,而是打印的時(shí)候代碼問題,按照這個(gè)代碼輸出的: %5ld , (long) thread_id 是個(gè)bug, 超過231就變成負(fù)數(shù)了,新版本改了 好問題 2019 02 28 1kun 感覺戛然而止哈 沒學(xué)夠,后面還會(huì)再回顧,老師辛苦! 2019 02 261亮 老師,sql 的where

28、里 10001 和 = 10000有什么區(qū)別嗎?2019 02 25 作者回復(fù) 這要看你關(guān)注的是什么 你這么問,應(yīng)該這個(gè)字段是整型吧? 從查詢結(jié)果可能是一樣的, 不過鎖的范圍不同,你可以看下21篇2019 02 25 IceGeek17 1 感謝老師,課程受益匪淺, 課程結(jié)束后,如果有問題,是繼續(xù)在這里的評(píng)論區(qū)提問,還是會(huì)有另外一條答疑通道? 另外,在第35篇我提了幾個(gè)問題,老師還沒有回答,我這里再貼一下,老師看一下問題一: 對(duì)于BKA算法的流程理解,用文中的例子,先把t1表(小表)中查詢需要的字段放入join_buffer, 然后把join_buffer里的字段值批量傳給t2表,先根據(jù)索引a

29、查到id,然后得到一批主鍵id,再根據(jù) 主鍵id排序,然后再根據(jù)排完序的id去主鍵索引查數(shù)據(jù)(這里用到MRR) 理解是否正確? 這里對(duì)于主鍵id排序是在哪里做的,是在join_buffer里,還是另外再開辟一塊臨時(shí)內(nèi)存?如果在j oin_buffer里,那join_buffer里的每行內(nèi)容是不是:t2.id + t1查詢必須的字段,并且join_buffer里是根據(jù)id排序的? 問題二: 雖然MySQL官方?jīng)]有支持hash join,但是之前看到文章說,MariaDB已經(jīng)支持hash join,能不能后續(xù)在答疑文章中簡單總結(jié)下mariaDB支持的join算法 問題三: 在實(shí)際項(xiàng)目中,一個(gè)比較困

30、惑的問題,看到過這樣的類似寫法: select xxx from t1 join t2 on t1.id = t2.id for update (目的是獲取幾個(gè)表上最新的數(shù)據(jù),并且加上鎖,防止數(shù)據(jù)被更新) 這里有幾個(gè)問題: 1) 像這樣 join + for update,表上的加鎖規(guī)則是怎么樣的?是不是在需要join的兩個(gè)表上根據(jù)具體的查詢執(zhí)行過程都加上鎖? 2)像這樣 join + for update 的用法是否合理?碰到這樣的場景,應(yīng)該怎么去做? 問題四: 看過阿里輸出的開發(fā)手冊(cè)里,強(qiáng)調(diào) “最多不超過三表join”,實(shí)際項(xiàng)目中,給我感覺很難做到所有業(yè)務(wù)都不超過三表join,那這里的問題

31、就是,有什么相關(guān)的經(jīng)驗(yàn)方法,可以盡量降低參與join的數(shù)據(jù)表? 比如,在數(shù)據(jù)表里添加冗余字段,可以降低參與join的數(shù)據(jù)表數(shù)量,還有什么其他好的方法? 2019 02 25 作者回復(fù) 就在我們?cè)u(píng)論區(qū),提跟文章相關(guān)的內(nèi)容,會(huì)繼續(xù)關(guān)注。 問題一、前面的過程理解正確,MRR過程用的是read_rnd_buffer 問題二、其實(shí)我們文中最后那個(gè)過程,你把他設(shè)想成在MySQL內(nèi)部執(zhí)行。問題三、這種復(fù)雜的語句,你要把我們兩部分知識(shí)點(diǎn)連起來看。一個(gè)原則:for update的話,執(zhí)行語句過程中掃到的間隙和記錄都要加鎖。 當(dāng)然最好是不這么做,拆成兩個(gè)語句會(huì)好些。 問題四、還是我文中的建議,如果都用NLJ或BKA算法的join其實(shí)還好,所以看看explain。降低join表數(shù)量的方法,基本上行就是冗余字段和拆成多個(gè)語句這兩個(gè)方向了 2019 02 25 1Leon 跟著老師終于學(xué)到了最后,每天的地鐵時(shí)間無比充實(shí),我對(duì)mysql的基本原理和工作流程大致有了初步的了解,而不是以前的增刪查改,打算以后抽時(shí)間再二刷三刷,等全部搞懂后,再去 看看高性能mysql這本書,如果時(shí)間允許,打算再去自己參照教程實(shí)現(xiàn)一個(gè)簡易的DB,課程雖 然結(jié)束了,仍然感覺意猶未盡,希望老師拉一個(gè)倍洽群,大家一起在里面討論和學(xué)習(xí) 2019 02 25作者回復(fù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論