在實現分庫分表的情況下,資料庫自增主鍵已無法保證自增主鍵的全局唯一。為此,MyCat 提供了全局 sequence,並且提供了包含本地配置和資料庫配置等多種實現方式, ...
1.MyCat中的全局序列號介紹
在實現分庫分表的情況下,資料庫自增主鍵已無法保證自增主鍵的全局唯一。為此,MyCat 提供了全局 sequence,並且提供了包含本地配置和資料庫配置等多種實現方式。
2.資料庫方式
原理:在資料庫中建立一張表,存放 sequence 名稱(name),sequence 當前值(current_value),步長(increment int 類型每次讀取多少個 sequence,假設為 K)等信息;
獲取步驟:
當初次使用該 sequence 時,根據傳入的 sequence 名稱,從資料庫這張表中讀取 current_value,和 increment 到 MyCat 中,並將資料庫中的 current_value 設置為原 current_value 值+increment 值; .
MyCat 將讀取到 current_value+increment 作為本次要使用的 sequence 值,下次使用時,自動加 1,當 使用 increment 次後,執行步驟 1)相同的操作. MyCat 負責維護這張表,用到哪些 sequence,只需要在這張表中插入一條記錄即可。若某次讀取的 sequence 沒有用完,系統就停掉了,則這次讀取的 sequence 剩餘值不會再使用。
3.配置資料庫方式
<3.1> 修改Mycat配置文件server.xml
<property name="sequnceHandlerType">1</property>
1代表使用資料庫方式生成sequence
<3.2> 修改Mycat配置文件schema.xml
<table name="test" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="mod-long"/> <table name="mycat_sequence" primaryKey="name" dataNode="dn2"/>
<3.3> 修改Mycat 配置文件 sequence_db_conf.properties,添加MYCAT=dn2
#sequence stored in datanode GLOBAL=dn1 COMPANY=dn1 CUSTOMER=dn1 ORDERS=dn1 MYCAT=dn2
<3.4> 在dn2節點的 db2 資料庫中添加 MYCAT_SEQUENCE表
DROP TABLE IF EXISTS MYCAT_SEQUENCE; CREATE TABLE MYCAT_SEQUENCE (name VARCHAR(50) NOT NULL,current_value INT NOT NULL,increment INT NOT NULL DEFAULT 100, PRIMARY KEY(name)) ENGINE=InnoDB;
<3.5> 在dn2節點的 db2 資料庫中的 MYCAT_SEQUENCE 表插入sequence初始記錄
INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES ('mycat', -99, 100);
代表插入了一個名為mycat的sequence,當前值為-99,步長為100。
<3.6> 在dn2節點的 db2 資料庫中創建存儲過程
(3.6.1) 獲取當前sequence的值:
DROP FUNCTION IF EXISTS mycat_seq_currval; DELIMITER $ CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN DECLARE retval VARCHAR(64); SET retval="-999999999,null"; SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR)) INTO retval FROM MYCAT_SEQUENCE WHERE name = seq_name; RETURN retval; END $ DELIMITER ;
(3.6.2) 設置sequence值:
DROP FUNCTION IF EXISTS mycat_seq_setval; DELIMITER $ CREATE FUNCTION mycat_seq_setval(seq_name VARCHAR(50),value INTEGER) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name; RETURN mycat_seq_currval(seq_name); END $ DELIMITER ;
(3.6.3) 獲取下一個sequence值:
DROP FUNCTION IF EXISTS mycat_seq_nextval; DELIMITER $ CREATE FUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment WHERE name = seq_name; RETURN mycat_seq_currval(seq_name); END $ DELIMITER ;
獲取全局id的配置已經準備完畢。
4.測試獲取全局自增ID
(4.1) 向dn1,dn2,dn3 中的db1,db2,db3 分別添加測試表 test
create table test(id int,name varchar(10));
(4.2) 重啟mycat ,使用WorkBench鏈接mycat
SELECT * FROM db2.mycat_sequence;
這是Mycat重啟之前的的 mycat_sequence初始化數據
這室mycat 重啟之後的 mycat_sequence 數據
(4.3) 向test表中添加測試數據,多次執行以下語句,這裡我執行了9次添加數據
insert into test(id,name) values(next value for MYCATSEQ_MYCAT,(select database()));
(4.4) 查詢添加的數據
SELECT * FROM test order by id asc;
全局自增id生成成功,同時數據被水平切分到 3個分片上
(4.5) 再次重啟mycat,執行(4.3)步驟,添加多次數據,之後查看 mycat_sequence 數據
發現在上次的基礎上增加了100
重啟後的id重101開始計數