1 Sequence簡介
DRDS sequence全稱:全局唯一數字序列,顧名思義,其作用是生成全局唯一和有序遞增的數字序列。常用于主鍵列、唯一索引列等值的生成。
Sequence分類,總共分為兩大類:
顯式sequence:通過sequence文法進行建立與維護,可以單獨使用。
隐式sequence:DRDS表主鍵定義 AUTO_INCREMENT後,用于自動填充主鍵,由 DRDS 自動維護
每類sequence針對不同的使用場景還分為四種類型,分别為Group Sequence,Group Sequence(單元化),Time-based Sequence,Simple Sequence。
詳情參考阿裡雲官網
本文重點介紹group隐式sequence。為什麼?
1、sequence原理性的東西,在官網上基本沒有展現,我們隻知其然而不知其是以然
2、當然是因為做DRDS資料遷移踩的關于隐式sequence的坑太多了,經常跟阿裡研發取經,加上環境測試了解到一些東西。
2 sequence的原理了解
1、sequence值是如何配置設定的?
如圖所示:DRDS在配置設定sequence的時候,會根據自身的節點數來劃分多個sequence段,預設每個段的長度為10萬。注意這裡是根據DRDS的規格節點數來劃分的sequence端,而不是根據RDS的數量,與RDS無關。
通過show sequences;指令,可以檢視目前sequence的value。
這裡的value值通常是表示已經配置設定的最大sequence段的起始值,即200000
2、sequence的起始值
有沒有發現上圖中,sequence段的起始值我是從100001開始取值的。預設情況下,sequence的起始值并不是按照1來開始遞增的,而是按照100001開始的。這就涉及到内部的一些算法:
(value - value % (innerStep unit_count)) + innerStep unit_count + nodeIndex * innerStep
實驗證明如下:
建立一張表,并且插入一條測試資料:
可以看到主鍵的id是從100001開始取值的。
3、sequence的緩存
這裡在節點上配置設定的sequence段,我們可以稱之為sequence的緩存,正常情況下,節點上的緩存用完才會重新配置設定sequence段。
緩存實驗測試如下:
truncate表清理了資料之後,重新插入資料還是會用到之前的緩存,從100002開始。
由于這種緩存的存在,尤其是DRDS在資料遷移的某些場景時,會産生很大的影響。
某客戶案例:
DRDS進行平台的資料遷移,由于沒有直接遷移DRDS to DRDS的工具,經過多次測試與衡量決定采用底層RDS to RDS方式的資料遷移。在第二次進行應用測試大批量報錯主鍵沖突。原因就是第一次測試完,truncate清理資料後,緩存還是存在的。第二次導入資料後則還是會用緩存的值,這時候測試插入資料就會出現主鍵沖突。
這裡出現sequence沖突的根本原因是,sequence本來是DRDS層面維護的,但是采用非标的方式遷移底層的RDS資料,雖然資料沒有問題,但sequence就沒有人來維護了。這樣就很容易出現很多問題。是以不到迫不得已盡量不要走非标方案。
解決方法:清理sequence緩存。
常用的清理緩存的方法:
1、alter sequence start with AUTO__XXXX;使用指令擡高sequence,指令是表級别的。
2、重新開機drds,目的是重新開機節點。
3、表删除重建立表
4、緩存的值是如何計算出來
我們已經知道,初始化的時候,sequence的值會按照算法定義起始值。那alter sequence start with AUTO__XXXX指令是如何更新sequence的value 以及 緩存的呢?
同理,alter sequence調整後,也會重新初始化sequence,先用算法更新起始值
(value - value % (innerStep unit_count)) + innerStep unit_count + unit_index * innerStep
然後再用下面的公式計算緩存區間:所有節點先後用公式計算
value + (inner_step * unit_count)
簡單的說:一般而言,執行指令alter後,首先會根據算法,将調整的sequence“合法化”,就是取整數,然後加一段區間更新到緩存,是以緩存會更新到一個更大的值。是以你會發現,在執行alter指令後,之後的主鍵值并不是按照修改的值遞增的,主鍵值肯定比調整的value要大。
測試驗證如下:
上圖可以看到,show sequence顯示的值為200000,與緩存中已配置設定的sequence段的最大值比對。
上圖中,随意調大了sequence的value,show sequence顯示為了432432,(這個隻是暫時顯示,後面還是會更新為最大sequence段的起始值)
上圖中,又插入了一條資料,發現show sequence的值已經改了。用指令查詢一下緩存,果然緩存已經更新了,并且是比alter設定的value值要大。
這裡還會發現,圖中第一次show sequence時,不是代表最大的sequence段的起始值。這是因為sequence值用到的時候才會更新這個value。
那為什麼執行檢視緩存的指令inspect後就恢複了呢?
猜測這個指令會強制重新整理value與緩存保持一緻。
那麼此時再插入資料主鍵會是從432432開始嗎?
當然不是了,如果你還覺得是,那就是之前我啰嗦的不夠透徹。
這裡就是按照緩存中的值來取sequence了。