1. 程式人生 > >MySQL分庫分表詳解

MySQL分庫分表詳解

一 分庫分表
1 什麼是分庫分表
– 將存放在一個數據庫(主機)中的資料,按照特定方式進行拆分,分散存放到多個數據庫(主機)中,以達到分散單臺裝置負載的效果。

2 垂直分隔
1) 縱向切分(分多個表)
–將單個表,拆分成多個表,分散到不同的資料庫
–將單個數據庫的多個表進行分類,按業務分類分散到不同的資料庫上。

3 水平分隔
1) 橫向切分(一個表分行)
–按照表中的某個欄位的某種規則,把表中的許多記錄按行切分,分散到多個數據庫中

二 maycat軟體介紹:
1 mycat 是基於java的分散式資料庫系統中間層,為高併發的分散式訪問提供解決方案
– 支援JDBC形式連線
– 支援mysql,oracle,sqlserver,mongodb等
– 可以實現資料庫伺服器的高可用
– 提供資料讀寫分離服務
– 提供資料分片服務
– 基與阿里巴巴Cobar進行研發的開源軟體
– 適合資料大量寫入的資料儲存需求

  1. 分片規則:
    1)列舉法 sharding-by-infile
    2)固定分片 rule1
    3)範圍約定 auto_sharding-long
    4) 求模法 mod-long
    5) 日期列分割槽法 sharding-by-date
    6) 通配取模 sharding-by-pattern
    7) ASCII 碼求模通配 sharding-by-prefixpattern
    8) 程式設計指定 sharding-by-substring
    9) 字串拆分hash解析 sharding-by-stringhash
    10) 一致性hash sharding-by-murmur

缺點: 查詢速度變慢,不適合讀取的環境。適合大併發寫入的環境
如何解決讀取數度慢的問題?

3 mycat工作過程:
當mycat收到一個SQL查詢時:
– 先解析這個SQL查詢涉及到的表
– 然後看此表的定義,如果有分片規則,則獲取SQL裡的分片欄位的值。並分配函式,獲取分片列表
– 然後將SQL發往這些分片去執行
– 最後收集和處理所有分片的結果資料,並返回到客戶端

三 配置Mycat
–環境: --資料庫伺服器2臺 192.168.4.54 192.168.4.55
–Mycat伺服器1臺 192.168.4.57
–客戶端 192.168.4.50
–2臺數據庫伺服器安裝mysql即可,不要開主從

1 檢視Mycat主機的java環境(因為Mycat是基於java開發的,所以需要jave環境的支援)

[[email protected] ~]# rpm -qa | grep -i jdk
java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64
java-1.8.0-openjdk-headless-1.8.0.131-11.b12.el7.x86_64
copy-jdk-configs-2.2-3.el7.noarch

[[email protected] ~]# java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)

2 解壓tar包

[[email protected] ~]# tar -xf Mycat-server-1.4-beta-20150604171601-linux.tar.gz  

3 將主配置檔案移動到/usr/local/下

[[email protected] ~]# mv  mycat/ /usr/local/
[[email protected] ~]# cd /usr/local/mycat/
[[email protected] mycat]# ls
bin  catlet  conf  lib  logs  version.txt

4 Mycat目錄結構說明
–bin //mycat 命令,如啟動 停止等
–catlet //擴充套件檔案
– conf //配置檔案
–lib //mycat使用的jar
–log //mycat啟動日誌和執行日誌
–wrapper.log //mycat服務啟動日誌
–mycat.log //記錄SQL指令碼執行後報錯的資訊

5 重要配置檔案說明:
–server.xml 設定連線mycat的帳號資訊
–schema.xml 配置mycat的真實庫表
–rule.xml 定義mycat分片規則

6 配置標籤說明:
<user……</user 定義連mycat使用者資訊
<datanode……</datanode 指定資料節點
<datahost……</datahost 指定資料庫地址及使用者資訊

7 配置57server.xml:

[[email protected] conf]# vim server.xml
34         <user name="admin">
35                 <property name="password">123456</property>
36                 <property name="schemas">TESTDB</property>
37         </user>
38 
39         <user name="user">
40                 <property name="password">user</property>
41                 <property name="schemas">TESTDB</property>
42                 <property name="readOnly">true</property>

8 修改57主配置檔案schema.xml

[[email protected] conf]# vim schema.xml
<schema
此標籤對內的dn3去掉
</schema>

    刪除39行的datanode
    37行 dataHost=mysql54
    38行 dataHost=mysql55
     37         <dataNode name="dn1" dataHost="mysql54" database="db1" />
     38         <dataNode name="dn2" dataHost="mysql55" database="db2" />
    ----- 去54上建立資料庫db1  去55上建立資料庫db2
    
42         <dataHost name="mysql54" maxCon="1000" minCon="10" balance="0"
43                 writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
44                 <heartbeat>select user()</heartbeat>
45                 <writeHost host="hostM1" url="192.168.4.54:3306" user="plj"
46                         password="123456">

47                 </writeHost>
48         </dataHost>
49 
50         <dataHost name="mysql55" maxCon="1000" minCon="10" balance="0"
51                 writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
52                 <heartbeat>select user()</heartbeat>
53                 <writeHost host="hostM2" url="192.168.4.55:3306" user="plj"
54                         password="123456">
55                 </writeHost>
56         </dataHost>

四 主機54 55資料庫上授權使用者plj 密碼為123456 用於mycat登入2臺數據庫。

1)修改資料庫配置檔案針對資料庫表名忽略大小寫

[[email protected] mysql]# vim /etc/my.cn
[mysqld]
lower_case_table_names = 1

2)使用者授權:用於mycat登入資料庫

mysql> grant all on *.* to [email protected]"%" identified by "123456";

3)54 上建立資料庫db1 在55上建立資料庫db2

4) 啟動服務

 [[email protected] ~]# /usr/local/mycat/bin/mycat start
 [[email protected] ~]# ss -antulp | grep 8066
tcp    LISTEN     0      100      :::8066                 :::*                   users:(("java",pid=1376,fd=49))

注意:啟動mycat時,發現8066埠查詢不到,檢視日誌

[[email protected] bin]# cat /usr/local/mycat/logs/wrapper.log
ERROR  | wrapper  | 2018/11/28 17:23:28 | JVM exited while loading the application.
INFO   | jvm 1    | 2018/11/28 17:23:28 | OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0
INFO   | jvm 1    | 2018/11/28 17:23:28 | OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000aaaa0000, 1431699456, 0) failed; error='Cannot allocate memory' (errno=12)

資訊提示無法分配記憶體,於是在57虛擬機器上加入一塊磁碟,重啟虛擬機器,然後就可以正常啟動mycat服務了

五 客戶端測試:
服務端50登入mycat伺服器

[[email protected] ~]# mysql -h192.168.4.57 -P8066 -uadmin -p123456
    mysql> show databases;
    +----------+
    | DATABASE |
    +----------+
    | TESTDB   |
    +----------+
    
mysql> use TESTDB;

mysql> show tables;
+------------------+
| Tables in TESTDB |
+------------------+
| company          |
| customer         |
| customer_addr    |
| employee         |
| goods            |
| hotnews          |
| orders           |
| order_items      |
| travelrecord     |
+------------------+
9 rows in set (0.00 sec)
#######################################################

1 建立employee 表(列舉法)

mysql> create table employee(id int primary key auto_increment,name varchar(12),sharding_id int);

具體檢視步驟:
第一步:查詢到這個表的規則:

[[email protected] conf]# vim schema.xml
                <table name="employee" primaryKey="ID" dataNode="dn1,dn2"
                        rule="sharding-by-intfile" />

第二步:進入規則表檢視具體規則的要求

[[email protected] conf]# vim rule.xml
        <tableRule name="sharding-by-intfile">
                <rule>
                        <columns>sharding_id</columns>
                        <algorithm>hash-int</algorithm>
                </rule>
        </tableRule>

        <function name="hash-int"
                class="org.opencloudb.route.function.PartitionByFileMap">
                <property name="mapFile">partition-hash-int.txt</property>
        </function>

第三步:根據指引檔案檢視具體的值

[[email protected] conf]# cat partition-hash-int.txt
10000=0             
10010=1
//建立employee必須要有欄位sharding_id ,插入資料為此欄位賦值10000的資料
 會被存放到54資料庫上去,賦值為10010的資料會被存放到55資料庫上去。

2 插入資料:

 mysql> insert into employee(name,sharding_id) values ("tom",10000),("kenji",10010);

3 進入54主機檢視資料:資料被存放到db1資料庫中的employee表中

mysql> select * from employee;
+----+------+-------------+
| id | name | sharding_id |
+----+------+-------------+
|  1 | tom  |       10000 |
+----+------+-------------+

4 進入55主機檢視資料:資料被存放到db2資料庫中的employee表中

mysql> select * from employee;
+----+-------+-------------+
| id | name  | sharding_id |
+----+-------+-------------+
|  1 | kenji |       10010 |
+----+-------+-------------+

################################################
1 建立表travelrecord :(範圍約定)

mysql> create table travelrecord(id int,name varchar(12));

具體檢視步驟:
第一步:查詢到這個表的規則:

[[email protected] conf]# vim schema.xml
<table name="travelrecord" dataNode="dn1,dn2" rule="auto-sharding-long" />

第二步:進入規則表檢視具體規則的要求

[[email protected] conf]# vim rule.xml
<tableRule name="auto-sharding-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>rang-long</algorithm>
                </rule>
        </tableRule>

<function name="rang-long"
                class="org.opencloudb.route.function.AutoPartitionByLong">
                <property name="mapFile">autopartition-long.txt</property>
        </function>

第三步:根據指引檔案檢視具體的值
[[email protected] conf]# vim autopartition-long.txt
 range start-end ,data node index
 K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
 //建立travelrecord必須要有欄位id ,插入資料為此欄位賦值0-500000的資料會被存放到54資料庫上去,賦值為的500001-10000000資料會被存放到55資料庫上去。

2 插入資料:

mysql> insert into travelrecord(id,name) values (5500000,"tom");
Query OK, 1 row affected (0.05 sec)

mysql> insert into travelrecord(id,name) values (50000,"tom");
Query OK, 1 row affected (0.07 sec)

3 進入54主機檢視資料:資料被存放到db1的travelrecord表中

 mysql> select * from travelrecord;
+-------+------+
| id    | name |
+-------+------+
| 50000 | tom  |
+-------+------+
1 row in set (0.00 sec)

4 進入55主機檢視資料:資料被存放到db2資料庫中的travelrecord表中

  mysql> select * from travelrecord;
+---------+------+
| id      | name |
+---------+------+
| 5500000 | tom  |
+---------+------+
1 row in set (0.00 sec)