溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法

發(fā)布時(shí)間:2021-09-07 11:10:39 來源:億速云 閱讀:186 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要介紹“mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法”,在日常操作中,相信很多人在mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

  • 前言

分庫(kù)分表,必不可少的步驟就是數(shù)據(jù)遷移。數(shù)據(jù)遷移又分兩種,一種是初始化遷移,另一種是上線期間的數(shù)據(jù)遷移。這里先考慮的是初始化遷移。

何為初始化遷移?其實(shí)就是將老庫(kù)的絕大部分?jǐn)?shù)據(jù)轉(zhuǎn)移到新庫(kù)中,一般這種遷移都是針對(duì)的是固定的數(shù)據(jù)。

  • 場(chǎng)景

      1.停機(jī)遷移(不推薦)
      2.數(shù)據(jù)雙寫遷移
      3.采用canal中間件遷移


以上三種一般是數(shù)據(jù)遷移的方案。第一種和第三種場(chǎng)景中都有遷移固定量的數(shù)據(jù)的步驟。這里暫不說遷移的方案的優(yōu)劣、選擇和實(shí)現(xiàn),后續(xù)再記錄這些,我今天先記錄一下我在初始化數(shù)據(jù)的時(shí)候碰到的問題以及解決的方案。

  • 問題

由于我想通過sql而非程序的方式來實(shí)現(xiàn)數(shù)據(jù)的初始化,因此這里碰到一個(gè)問題。

我需要通過hash來決定分到哪個(gè)庫(kù)或者表,然而java的String類型有hashCode方法,那mysql呢?

經(jīng)過一番查找之后,發(fā)現(xiàn)mysql并不支持hash方法,那咋辦呢,只能通過存儲(chǔ)過程來寫一個(gè)自定義函數(shù)了。那就直接開始操作了!

  • 操作

mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法

由上圖可知,java中String的hashCode這么實(shí)現(xiàn)的,關(guān)鍵點(diǎn)就是這行代碼

h = 31 * h + val[i];

簡(jiǎn)單介紹下,他其實(shí)就是對(duì)字符串轉(zhuǎn)成Char數(shù)組,然后進(jìn)行循環(huán)。每次循環(huán)都對(duì)hash值 * 31,然后加上char的ASCII值。最后循環(huán)完成得到的值就是這個(gè)字符串最后的hashCode值。

那我們?cè)趍ysql的自定義函數(shù)里面也按這個(gè)邏輯這么寫就好了,如下:

DELIMITER $$
CREATE FUNCTION hash_code (user_id VARCHAR(50)) RETURNS INT
BEGIN

DECLARE result INT DEFAULT 0 ;
DECLARE num INT DEFAULT 1 ;
WHILE (num <= LENGTH(user_id)) DO

SET result = result * 31 + ASCII(SUBSTRING(user_id, num, 1)) ;
SET num = num + 1 ;
END
WHILE ;
IF result < 0 THEN

SET result = result * - 1 ;
END
IF ; RETURN result ; END$$

但是經(jīng)過測(cè)試了之后發(fā)現(xiàn),超過了INT的范圍了,尷尬。看來只能再優(yōu)化下了。

然后發(fā)現(xiàn)java中超過INT范圍之后,他會(huì)自己進(jìn)行補(bǔ)碼。舉個(gè)易懂的例子,看如下代碼:

    int num = 0;
    for (int i = 0; ; i++) {
        num++;
        System.out.println(num);
    }

上面的代碼無限相加,打印出來的Num會(huì)是什么,有興趣的大家可以試一下。

我這邊先直接說結(jié)果,如下:

0 --> 1 --> 2 .... --> Integer.MAX_VALUE(2147483647) --> -2147483648 --> -2147483647 --> -2147483646 .... --> 2 --> 1 --> 0

是不是找到規(guī)律了?那就直接操作了!一步一步來,先來一個(gè)相同數(shù)相加的程序

DELIMITER $$
CREATE FUNCTION int_add (num BIGINT) RETURNS BIGINT
BEGIN

DECLARE result BIGINT ;
SET result = num ;
IF result >= 0 THEN

IF 2147483647 - result >= result THEN

SET result = result + result ;
ELSE

SET result = (2147483648 - result) * - 2 ;
END
IF ;
ELSE

IF result >= - 1073741824 THEN

SET result = result + result ;
ELSE

SET result = (- 2147483648 - result) * - 2 ;
END
IF ;
END
IF ; RETURN result ; END$$

DELIMITER ;

寫完發(fā)現(xiàn)自己有點(diǎn)蠢了,為了數(shù)字不超過INT的最大范圍做了很多操作和判斷,那我為啥不利用下BIGINT呢?超過INT也沒事,超過之后再將他的數(shù)值更正回來即可。那就直接換個(gè)更簡(jiǎn)單的方法吧!

DELIMITER $$
CREATE FUNCTION int_add_new (num BIGINT, addNum BIGINT) RETURNS BIGINT
BEGIN

DECLARE result BIGINT ;
SET result = num + addNum ;
IF result > 2147483647 THEN

SET result = - 2147483648 + (result - 2147483648) ;
ELSEIF result < - 2147483648 THEN

SET result = 2147483647 - (- 2147483649 - result) ;
END
IF ; RETURN result ; END$$

DELIMITER ;

或者直接乘呢

DELIMITER $$
CREATE FUNCTION int_multiply (num BIGINT, multiplyNum BIGINT) RETURNS BIGINT
BEGIN

DECLARE result BIGINT ;
SET result = (num * addNum) % (2147483648 * 2) ;
IF result > 2147483647 THEN

SET result = - 2147483648 + (result - 2147483648) ;
ELSEIF result < - 2147483648 THEN

SET result = 2147483647 - (- 2147483649 - result) ;
END
IF ; RETURN result ; END$$

DELIMITER ;

嗯,確實(shí)看起來容易太多了。這一步ok了之后,接下去通過調(diào)用這個(gè)方法再去寫HashCode方法就簡(jiǎn)單多啦,如下:

DELIMITER $$
CREATE FUNCTION hash_code (user_id VARCHAR(50), hashNum INT) RETURNS INT
BEGIN

DECLARE result BIGINT DEFAULT 0 ;
DECLARE num INT DEFAULT 1 ;
DECLARE tempNum INT;
DECLARE tempResult BIGINT;
WHILE (num <= LENGTH(user_id)) DO

SET tempNum = 1 ;
SET tempResult = result ;
WHILE (tempNum <= 30) DO

SET result = int_add_new (result, tempResult) ;
SET tempNum = tempNum + 1 ;
END
WHILE ;
SET result = int_add_new (
    result,
    ASCII(SUBSTRING(user_id, num, 1))
) ;
SET num = num + 1 ;
END
WHILE ;
IF result < 0 THEN

SET result = result * - 1 ;
END
IF ; RETURN result % hashNum ; END$$

DELIMITER ;

大功告成,直接試一下!

mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法

接下去和java程序?qū)Ρ纫幌拢Y(jié)果也對(duì)上啦,nice!

啊,突然想到如果大家碰到了這個(gè)問題的話

mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法

這個(gè)是因?yàn)闆]允許自定義函數(shù),運(yùn)行下下面的指令就ok拉!

set global log_bin_trust_function_creators=TRUE;

到此,關(guān)于“mysql分庫(kù)分表和數(shù)據(jù)初始化遷移的方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI