MySQL8.0.15基於mycat讀寫分離(windows環境)
系統開發中,資料庫是非常重要的一個點。除了程式的本身的優化,如:SQL語句優化、程式碼優化,資料庫的處理本身優化也是非常重要的。主從、熱備、分表分庫等都是系統發展遲早會遇到的技術問題問題。Mycat是一個廣受好評的資料庫中介軟體,已經在很多產品上進行使用了。下面就針對Mycat的基礎知識和應用做一總結性梳理,這些內容有的是從網上收集的,有的是自己做的測試驗證資訊,如有錯誤,煩請諒解和指出!
一、MyCat簡單介紹
MyCat是一個開源的分散式資料庫系統,是一個實現了MySQL協議的伺服器,前端使用者可以把它看作是一個數據庫代理(類似於Mysql Proxy),用MySQL客戶端工具和命令列訪問,而其後端可以用MySQL原生協議與多個MySQL伺服器通訊,也可以用JDBC協議與大多數主流資料庫伺服器通訊,其核心功能是分表分庫,即將一個大表水平分割為N個小表,儲存在後端MySQL伺服器裡或者其他資料庫裡。
MyCat發展到目前的版本,已經不是一個單純的MySQL代理了,它的後端可以支援MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流資料庫,也支援MongoDB這種新型NoSQL方式的儲存,未來還會支援更多型別的儲存。而在終端使用者看來,無論是那種儲存方式,在MyCat裡,都是一個傳統的資料庫表,支援標準的SQL語句進行資料的操作,這樣一來,對前端業務系統來說,可以大幅降低開發難度,提升開發速度。
Mycat可以簡單概括為
- 一個徹底開源的,面向企業應用開發的大資料庫叢集
- 支援事務、ACID、可以替代MySQL的加強版資料庫
- 一個可以視為MySQL叢集的企業級資料庫,用來替代昂貴的Oracle叢集
- 結合傳統資料庫和新型分散式資料倉庫的新一代企業級資料庫產品
- 一個新穎的資料庫中介軟體產品
Mycat關鍵特性
- 支援SQL92標準
- 遵守Mysql原生協議,跨語言,跨平臺,跨資料庫的通用中介軟體代理
-基於心跳的自動故障切換,支援讀寫分離,支援MySQL主從,以及galera cluster叢集
- 支援Galera for MySQL叢集,Percona Cluster或者MariaDB cluster
- 基於Nio實現,有效管理執行緒,高併發問題
- 支援資料的多片自動路由與聚合,支援sum,count,max等常用的聚合函式,支援跨庫分頁
- 支援通過全域性表,ER關係的分片策略,實現了高效的多表join查詢
- 支援多租戶方案
- 支援分散式事務(弱xa)
- 支援全域性序列號,解決分散式下的主鍵生成問題
- 分片規則豐富,外掛化開發,易於擴充套件
- 強大的web,命令列監控
- 支援前端作為mysq通用代理,後端JDBC方式支援Oracle、DB2、SQL Server 、 mongodb 、巨杉
- 支援密碼加密
- 支援服務降級
- 支援IP白名單
- 支援SQL黑名單、sql注入攻擊攔截
- 支援分表(1.6)
- 叢集基於ZooKeeper管理,線上升級,擴容,智慧優化,大資料處理(2.0開發版)
二、為什麼要用MyCat
這裡要先搞清楚Mycat和MySQL的區別(Mycat的核心作用)。我們可以把上層看作是對下層的抽象,例如作業系統是對各類計算機硬體的抽象。那麼我們什麼時候需要抽象?假如只有一種硬體的時候,我們需要開發一個作業系統嗎?再比如一個專案只需要一個人完成的時候不需要leader,但是當需要幾十人完成時,就應該有一個管理者,發揮溝通協調等作用,而這個管理者對於他的上層來說就是對專案組的抽象。
同樣的,當我們的應用只需要一臺資料庫伺服器的時候我們並不需要Mycat,而如果你需要分庫甚至分表,這時候應用要面對很多個數據庫的時候,這個時候就需要對資料庫層做一個抽象,來管理這些資料庫,而最上面的應用只需要面對一個數據庫層的抽象或者說資料庫中介軟體就好了,這就是Mycat的核心作用。所以可以這樣理解:資料庫是對底層儲存檔案的抽象,而Mycat是對資料庫的抽象。
三、Mycat工作原理
Mycat的原理並不複雜,複雜的是程式碼。Mycat的原理中最重要的一個動詞是“攔截”,它攔截了使用者傳送過來的SQL語句,首先對SQL語句做了一些特定的分析:如分
片分析、路由分析、讀寫分離分析、快取分析等,然後將此SQL發往後端的真實資料庫,並將返回的結果做適當的處理,最終再返回給使用者。
上述圖片裡,Orders表被分為三個分片datanode(簡稱dn),這三個分片是分佈在兩臺MySQL Server上(DataHost),即datanode=database@datahost方式,因此你可以用一臺到N臺伺服器來分片,分片規則為(sharding rule)典型的字串列舉分片規則,一個規則的定義是分片欄位(sharding column)+分片函式(rule function),這裡的分片欄位為prov而分片函式為字串列舉方式。
當Mycat收到一個SQL時,會先解析這個SQL,查詢涉及到的表,然後看此表的定義,如果有分片規則,則獲取到SQL裡分片欄位的值,並匹配分片函式,得到該SQL對應的分片列表,然後將SQL發往這些分片去執行,最後收集和處理所有分片返回的結果資料,並輸出到客戶端。以select * from Orders where prov=?語句為例,查到prov=wuhan,按照分片函式,wuhan返回dn1,於是SQL就發給了MySQL1,去取DB1上的查詢結果,並返回給使用者。
如果上述SQL改為select * from Orders where prov in (‘wuhan’,‘beijing’),那麼,SQL就會發給MySQL1與MySQL2去執行,然後結果集合並後輸出給使用者。但通常業務中我們的SQL會有Order By 以及Limit翻頁語法,此時就涉及到結果集在Mycat端的二次處理,這部分的程式碼也比較複雜,而最複雜的則屬兩個表的Jion問題,為此,Mycat提出了創新性的ER分片、全域性表、HBT(Human Brain Tech)人工智慧的Catlet、以及結合Storm/Spark引擎等十八般武藝的解決辦法,從而成為目前業界最強大的方案,這就是開源的力量!
四、Mycat應用場景
Mycat發展到現在,適用的場景已經很豐富,而且不斷有新使用者給出新的創新性的方案,以下是幾個典型的應用場景:
- 單純的讀寫分離,此時配置最為簡單,支援讀寫分離,主從切換;
- 分表分庫,對於超過1000萬的表進行分片,最大支援1000億的單表分片;
- 多租戶應用,每個應用一個庫,但應用程式只連線Mycat,從而不改造程式本身,實現多租戶化;
- 報表系統,藉助於Mycat的分表能力,處理大規模報表的統計;
- 替代Hbase,分析大資料;
- 作為海量資料實時查詢的一種簡單有效方案,比如100億條頻繁查詢的記錄需要在3秒內查詢出來結果,除了基於主鍵的查詢,還可能存在範圍查詢或其他屬性查詢,此時Mycat可能是最簡單有效的選擇;
- Mycat長期路線圖;
- 強化分散式資料庫中介軟體的方面的功能,使之具備豐富的外掛、強大的資料庫智慧優化功能、全面的系統監控能力、以及方便的資料運維工具,實現線上資料擴容、遷移等高階功能;
- 進一步挺進大資料計算領域,深度結合Spark Stream和Storm等分散式實時流引擎,能夠完成快速的巨表關聯、排序、分組聚合等 OLAP方向的能力,並整合一些熱門常用的實時分析演算法,讓工程師以及DBA們更容易用Mycat實現一些高階資料分析處理功能。
- 不斷強化Mycat開源社群的技術水平,吸引更多的IT技術專家,使得Mycat社群成為中國的Apache,並將Mycat推到Apache
基金會,成為國內頂尖開源專案,最終能夠讓一部分志願者成為專職的Mycat開發者,榮耀跟實力一起提升。
五、Mycat不適合的應用場景
- 設計使用Mycat時有非分片欄位查詢,請慎重使用Mycat,可以考慮放棄!
- 設計使用Mycat時有分頁排序,請慎重使用Mycat,可以考慮放棄!
- 設計使用Mycat時如果要進行表JOIN操作,要確保兩個表的關聯欄位具有相同的資料分佈,否則請慎重使用Mycat,可以考慮放棄!
- 設計使用Mycat時如果有分散式事務,得先看是否得保證事務得強一致性,否則請慎重使用Mycat,可以考慮放棄!
需要注意:在生產環境中, Mycat節點最好使用雙節點, 即雙機熱備環境, 防止Mycat這一層出現單點故障.可以使用的高可用叢集方式有:Keepalived+Mycat+Mysql,Keepalived+LVS+Mycat+Mysql,Keepalived+Haproxy+Mycat+Mysql
六、利用MyCAT實現MySQL的讀寫分離、主從切換、分庫分表的操作記錄
Mycat實現Mysql主從複製,其中寫操作在master主節點上執行,包括insert,delete,update 語句操作;讀操作在slave節點上執行,只有select語句操作,其他操作均由主master的二進位制檔案決定;MyCat支援雙主多從,多主多從情況需要配置多個writeHost兄弟節點,多個readHost節點即可!
Mycat的架構其實很好理解,Mycat是資料庫代理中介軟體,Mycat後面就是物理資料庫。和Web伺服器的Nginx類似。對於使用者來說,訪問的都是Mycat,不會接觸到後端的資料庫。如下案例是做一個主從、讀寫分離,簡單分庫分表的示例。結構如下圖:
伺服器資訊如下(實驗環境,關閉機器的iptables防火牆和selinux):
1 2 3 4 5 6 7 8 9 10 11 12 |
伺服器主機名 ip 說明
Mycat-node 192.168.10.210 mycat伺服器,連線資料庫時,連線此伺服器
Mysql-node1 192.168.10.205 物理資料庫1,真正儲存資料的資料庫,這裡為Master主資料庫
Mysql-node2 192.168.10.206 物理資料庫2,真正儲存資料的資料庫,這裡為Slave主資料庫
三臺機器分佈修改主機名,並做hosts繫結
# vim /etc/hosts
192.168.10.205 Mysql-node1
192.168.10.206 Mysql-node1
192.168.10.210 Mycat-node
為方便做實驗,關閉三臺機器的iptables防火牆和selinux
|
Mycat作為主資料庫中介軟體,肯定是與程式碼弱關聯的,所以程式碼是不用修改的,使用Mycat後,連線資料庫是不變的,預設埠是8066。連線方式和普通資料庫一樣,比如:jdbc:mysql://192.168.10.210:8066/
1)Mysql安裝及主從複製部署(Mysql-node1和Mysql-node2兩臺機器上操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
a)安裝Mysql,安裝過程要在兩個Mysql節點機器上都要操作。
安裝過程參考:http: //www .cnblogs.com /kevingrace/p/6109679 .html
這裡省去安裝過程~~
b)Mysql主從複製(兩個節點的mysql登入使用者名稱和密碼都是root /123456 )
參考:http: //www .cnblogs.com /kevingrace/p/6256603 .html
====================================================
首先是Mysql-node1主節點配置操作
[root@Mysql-node1 ~] # cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node1 ~] # vim /usr/local/mysql/my.cnf #在[mysqld]區域新增下面內容
......
[mysqld]
server- id =1
log-bin=mysql-bin
#binlog-do-db=kevin #需要同步的資料庫。如果是多個同步庫,就以此格式另寫幾行即可。如果不指明對某個具體庫同步,就去掉此行,表示同步所有庫(除了ignore忽略的庫)
binlog-ignore-db = mysql,information_schema
sync_binlog = 1
binlog_checksum = none
binlog_format = mixed
重啟mysql服務
[root@Mysql-node1 ~] # /etc/init.d/mysql restart
登入mysql,授予slave從機複製許可權
mysql> grant replication slave,replication client on *.* to slave@ '192.168.10.206' identified by "slave@123" ;
Query OK, 0 rows affected (0.05 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.06 sec)
授權之後,要保證192.168.10.206這臺slave節點機器能使用上面的許可權資訊登入到本機的mysql
將資料庫鎖住,僅僅允許讀,以保證資料一致性;
mysql> FLUSH TABLES WITH READ LOCK; #注意,鎖定後,如果自己同步對方資料,同步前一定要記得先解鎖!
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.05 sec)
檢視主節點的master複製資訊
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 | 1349 | | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)
====================================================
接著是slave從節點操作
[root@Mysql-node2 ~] # cp /usr/local/mysql/my.cnf /usr/local/mysql/my.cnf.bak
[root@Mysql-node2 ~] # vim /usr/local/mysql/my.cnf
.......
[mysqld]
.......
server- id =2
log-bin=mysql-bin
#replicate-do-db=kevin #需要同步的資料庫名。如果不指明同步哪些庫,就去掉這行,表示所有庫的同步(除了ignore忽略的庫)。
replicate-ignore-db=mysql
slave-skip-errors = all
重啟mysql服務
[root@Mysql-node2 ~] # /etc/init.d/mysql restart
登入slave節點的mysql,進行主從同步設定
mysql> stop slave;
Query OK, 0 rows affected (0.09 sec)
mysql> change master to master_host= '192.168.10.205' ,master_user= 'slave' ,master_password= 'slave@123' ,master_log_file= 'mysql-bin.000003' ,master_log_pos=1349;
Query OK, 0 rows affected, 2 warnings (0.21 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.205
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1349
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1349
Relay_Log_Space: 456
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 747977ea-8fba-11e8-86c0-525400b19c93
Master_Info_File: /data/mysql/data/master .info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I /O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>
=========================================================
通過上面的資訊,可知主從複製環境已經OK(Slave_IO_Running和Slave_SQL_Running狀態均為YES),下面驗證下主從複製是否正常?
在Mysql-node1主節點上操作
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.06 sec)
mysql> use kevin;
Database changed
mysql> create table if not exists haha ( id int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);
Query OK, 0 rows affected (0.34 sec)
在Mysql-node2從節點上檢視(保證從節點上檢視slave狀態時,Slave_IO_Running和Slave_SQL_Running狀態均為YES,這樣就能保證主從複製在進行中)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kevin |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> use kevin;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
接著在Mysql-node1主節點插入資料
mysql> insert into kevin.haha values(1, "wangshibo" ),(2, "linan" ),(3, "zhangminmin" );
Query OK, 3 rows affected (0.04 sec)
Records: 3 Duplicates: 0 Warnings: 0
然後再在MYsql-node2從節點檢視,如下發現已經同步過來了!
mysql> use kevin;
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows in set (0.00 sec)
由此可見,Mysql的主從複製已經實現!
|
2)Mycat中介軟體安裝、配置和測試(Mycat-node節點機器上操作)
2.1)Mycat安裝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
建議下載1.6-RELEASE 版本,畢竟是比較穩定的版本。
下載官網地址:http: //dl .mycat.io/
[root@Mycat-node ~] # cd /usr/local/src/
[root@Mycat-node src] # wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src] # tar -zvxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@Mycat-node src] # mv mycat /data/
[root@Mycat-node src] # ls /data/mycat/
bin catlet conf lib logs version.txt
mycat安裝完成後,目錄如下:
bin mycat命令,啟動、重啟、停止等
catlet catlet為Mycat的一個擴充套件功能
conf Mycat 配置資訊,重點關注
lib Mycat引用的jar包,Mycat是java開發的
logs 日誌檔案,包括Mycat啟動的日誌和執行的日誌。
Mycat的配置檔案都在conf目錄裡面,這裡介紹幾個常用的檔案:
server.xml Mycat的配置檔案,設定賬號、引數等
schema.xml Mycat對應的物理資料庫和資料庫表的配置
rule.xml Mycat分片(分庫分表)規則
[root@Mycat-node src] # cd /data/mycat/conf
[root@Mycat-node conf] # ll server.xml
-rwxrwxrwx. 1 root root 3740 Jul 25 12:19 server.xml
[root@Mycat-node conf] # ll schema.xml
-rwxrwxrwx. 1 root root 4667 Jul 31 02:54 schema.xml
|
2.2)Mycat相關配置
server.xml檔案其實跟讀寫分離策略關係不大,但是需要用此檔案來配置連線MyCat的使用者及許可權等,因此在這裡簡單說明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
[root@Mycat-node conf] # cp server.xml server.xml.bak
[root@Mycat-node conf] # vim server.xml
.......
<user name= "bobo" >
<property name= "password" >bo@123< /property >
<property name= "schemas" >mycat /property >
<!-- 表級 DML 許可權設定 -->
<!--
<privileges check= "false" >
<schema name= "TESTDB" dml= "0110" >
<table name= "tb01" dml= "0000" >< /table >
<table name= "tb02" dml= "1111" >< /table >
< /schema >
< /privileges >
-->
< /user >
<!-- #注意,由於這裡只定義了一個標籤,所以把多餘的都註釋了。如果這個開啟,也需要將TESTDB庫改為和上面一樣的mycat庫名。
<user name= "user" >
<property name= "password" >user< /property >
<property name= "schemas" >TESTDB< /property >
<property name= "readOnly" > true < /property >
< /user >
-->
< /mycat :server>
.......
重點關注上面這段配置,其他預設即可。
=======================================
引數 說明
user 使用者配置節點
name 登入的使用者名稱,也就是連線Mycat的使用者名稱。
password 登入的密碼,也就是連線Mycat的密碼
schemas 資料庫名,這裡會和schema.xml中的配置關聯,多個用逗號分開,例如需要這個使用者需要管理兩個資料庫db1,db2,則配置db1,dbs
privileges 配置使用者針對表的增刪改查的許可權
readOnly mycat邏輯庫所具有的許可權。 true 為只讀, false 為讀寫都有,預設為 false 。
=======================================
我這裡配置了一個賬號boo,密碼為bo@123,邏輯資料庫為mycat,這些資訊都可以自己隨意定義,讀寫許可權都有,沒有針對表做任何特殊的許可權。
注意:
- server.xml檔案裡登入mycat的使用者名稱和密碼可以任意定義,這個賬號和密碼是為客戶機登入mycat時使用的賬號資訊。
- 邏輯庫名(如上面的mycat,也就是登入mycat後顯示的庫名,切換這個庫之後,顯示的就是代理的真實mysql資料庫的表)要在schema.xml裡面也定義,否則會導致mycat服務啟動失敗!
- 這裡只定義了一個標籤,所以把多餘的都註釋了。如果定義多個標籤,即設定多個連線mycat的使用者名稱和密碼,那麼就需要在schema.xml檔案中定義多個對應的庫!
|
schema.xml是最主要的配置項,此檔案關聯mysql讀寫分離策略!讀寫分離、分庫分表策略、分片節點都是在此檔案中配置的!
MyCat作為中介軟體,它只是一個代理,本身並不進行資料儲存,需要連線後端的MySQL物理伺服器,此檔案就是用來連線MySQL伺服器的!
schemaxml檔案中配置的引數解釋
1 2 3 4 |
引數 說明
schema 資料庫設定,此資料庫為邏輯資料庫,name與server.xml中schema對應
dataNode 分片資訊,也就是分庫相關配置
dataHost 物理資料庫,真正儲存資料的資料庫
|
配置說明
1 2 3 4 |
name屬性唯一標識dataHost標籤,供上層的標籤使用。
maxCon屬性指定每個讀寫例項連線池的最大連線。也就是說,標籤內巢狀的
writeHost、readHost標籤都會使用這個屬性的值來例項化出連線池的最大連線數。
minCon屬性指定每個讀寫例項連線池的最小連線,初始化連線池的大小。
|
每個節點的屬性逐一說明
1 2 3 4 5 |
schema:
屬性 說明
name 邏輯資料庫名,與server.xml中的schema對應
checkSQLschema 資料庫字首相關設定,建議看文件,這裡暫時設為folse
sqlMaxLimit select 時預設的limit,避免查詢全表
|
table
1 2 3 4 5 6 |
屬性 說明
name 表名,物理資料庫中表名
dataNode 表儲存到哪些節點,多個節點用逗號分隔。節點為下文dataNode設定的name
primaryKey 主鍵欄位名,自動生成主鍵時需要設定
autoIncrement 是否自增
rule 分片規則名,具體規則下文rule詳細介紹
|
dataNode
1 2 3 4 |
屬性 說明
name 節點名,與table中dataNode對應
datahost 物理資料庫名,與datahost中name對應
database 物理資料庫中資料庫名
|
dataHost
1 2 3 4 5 6 |
屬性 說明
name 物理資料庫名,與dataNode中dataHost對應
balance 均衡負載的方式
writeType 寫入方式
dbType 資料庫型別
heartbeat 心跳檢測語句,注意語句結尾的分號要加
|
schema.xml檔案中有三點需要注意:balance="1",writeType="0" ,switchType="1"
schema.xml中的balance的取值決定了負載均衡對非事務內的讀操作的處理。balance 屬性負載均衡型別,目前的取值有 4 種:
1 2 3 4 5 6 7 8 9 10 |
balance= "0" : 不開啟讀寫分離機制,所有讀操作都發送到當前可用的writeHost 上,即讀請求僅傳送到writeHost上。
balance= "1" : 讀請求隨機分發到當前writeHost對應的readHost和standby的writeHost上。即全部的readHost與stand by writeHost 參與
select 語句的負載均衡,簡單的說,當雙主雙從模式(M1 ->S1 , M2->S2,並且 M1 與 M2 互為主備),正常情況下, M2,S1,
S2 都參與 select 語句的負載均衡
balance= "2" : 讀請求隨機分發到當前dataHost內所有的writeHost和readHost上。即所有讀操作都隨機的在writeHost、 readhost 上分發。
balance= "3" : 讀請求隨機分發到當前writeHost對應的readHost上。即所有讀請求隨機的分發到 wiriterHost 對應的 readhost 執行,
writerHost 不負擔讀壓力,注意 balance=3 只在 1.4 及其以後版本有,1.3 沒有。
|
writeType 屬性,負載均衡型別,目前的取值有 3 種
1 2 3 |
writeType= "0" 所有寫操作傳送到配置的第一個 writeHost,第一個掛了切到還生存的第二個writeHost,重新啟動後已切換後的為準,切換記錄在配置檔案中:dnindex.properties .
writeType= "1" 所有寫操作都隨機的傳送到配置的 writeHost。
writeType= "2" 沒實現。
|
對於事務內的SQL預設走寫節點
1 2 3 4 5 |
以 /*balance*/ 開頭,可以指定SQL使用特定負載均衡方案。例如在大環境開啟讀寫分離的情況下,特定強一致性的SQL查詢需求;
slaveThreshold:近似的主從延遲時間(秒)Seconds_Behind_Master < slaveThreshold ,讀請求才會分發到該Slave,確保讀到的資料相對較新。
schema.xml中的writeType的取值決定了負載均衡對寫操作的處理:
writeType= "0" :所有的寫操作都發送到配置檔案中的第一個write host。(第一個write host故障切換到第二個後,即使之後修復了仍然維持第二個為寫庫)。推薦取0值,不建議修改.
|
主從切換(雙主failover):switchType 屬性
1 2 3 4 5 6 7 8 |
如果細心觀察schem.xml檔案的話,會發現有一個引數:switchType,如下配置:
<dataHost name= "237_15" maxCon= "1000" minCon= "10" balance= "1" writeType= "0" dbType= "mysql" dbDriver= "native" switchType= "1" slaveThreshold= "100" >
引數解讀
switchType= "-1" : 不自動切換
switchType= "1" : 預設值,自動切換
switchType= "2" : 基於MySQL主從同步的狀態來決定是否切換。需修改heartbeat語句(即心跳語句):show slave status
switchType= "3" : 基於Mysql Galera Cluster(叢集多節點複製)的切換機制。需修改heartbeat語句(即心跳語句):show status like 'wsrep%'
|
dbType屬性
1 |
指定後端連線的資料庫型別,目前支援二進位制的mysql協議,還有其他使用JDBC連線的資料庫。例如:mongodb、oracle、spark等。
|
dbDriver屬性指定連線後端資料庫使用的
1 2 3 4 5 6 7 |
Driver,目前可選的值有native和JDBC。
使用native的話,因為這個值執行的是二進位制的mysql協議,所以可以使用mysql和maridb。
其他型別的資料庫則需要使用JDBC驅動來支援。從1.6版本開始支援postgresql的native原始協議。
如果使用JDBC的話需要將符合JDBC 4標準的驅動JAR包放到MYCAT\lib目錄下,並檢查驅動JAR包中包括如下目錄結構的檔案:
META-INF\services\java.sql.Driver。在這個檔案內寫上具體的Driver類名,例如:com.mysql.jdbc.Driver。
|
heartbeat標籤
1 2 3 4 5 6 |
這個標籤內指明用於和後端資料庫進行心跳檢查的語句。例如,MYSQL可以使用 select user(),Oracle可以使用 select 1 from dual等。
這個標籤還有一個connectionInitSql屬性,主要是當使用Oracla資料庫時,需要執行的初始化SQL
語句就這個放到這裡面來。例如:altersession set nls_date_format= 'yyyy-mm-dd hh24:mi:ss'
1.4主從切換的語句必須是:showslave status
|
writeHost標籤、readHost標籤
1 2 3 4 5 6 |
這兩個標籤都指定後端資料庫的相關配置給mycat,用於例項化後端連線池。
唯一不同的是:writeHost指定寫例項、readHost指定讀例項,組著這些讀寫例項來滿足系統的要求。
在一個dataHost內可以定義多個writeHost和readHost。但是,如果writeHost指定的後端資料庫宕機,那麼這個writeHost繫結的所有readHost都將不可用。
另一方面,由於這個writeHost宕機系統會自動的檢測到,並切換到備用的writeHost上去。
|
應用場景1--->Mycat讀寫分離(負載均衡)、主從自動切換
目前有大量Mycat的生產實踐案例是屬於簡單的讀寫分離型別的,此案例主要用到Mycat的以下特性:
- 讀寫分離支援
- 高可用
大多數讀寫分離的案例是同時支援高可用性的,即Mycat+MySQL主從複製的叢集,並開啟Mycat的讀寫分離功能,這種場景需求下,Mycat是最為簡單並且功能最為
豐富的一類Proxy,正常情況下,配置檔案也最為簡單,不用每個表配置,只需要在schema.xml中的元素上增加dataNode=“defaultDN”屬性,並配置此dataNode
對應的真實物理資料庫的database,然後dataHost開啟讀寫分離功能即可。
修改mycat的schema.xml:
balance為1:讓全部的readHost及備用的writeHost參與select的負載均衡。
switchType為2:基於MySQL主從同步的狀態決定是否切換。
heartbeat:主從切換的心跳語句必須為show slave status。
僅僅進行讀寫分離的schema.xml配置(備份原來的schema.xml檔案,清空,直接複製下面內容):不想要自動切換功能,即MySQL寫節點宕機後不自動切換到備用節點:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[root@Mycat-node conf] # vim schema.xml
<?xml version= "1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd" >
<mycat:schema xmlns:mycat= "http://io.mycat/" >
<schema name= "mycat" checkSQLschema= "false" sqlMaxLimit= "100" dataNode= "haha" >
< /schema >
<dataNode name= "haha" dataHost= "Mycat-node" database= "kevin" />
<dataHost name= "Mycat-node" maxCon= "1000" minCon= "10" balance= "1" writeType= "0" dbType= "mysql" dbDriver= "native" switchType= "1" slaveThreshold= "100" >
<heartbeat>show slave status< /heartbeat >
<writeHost host= "Mysql-node1" url= "192.168.10.205:3306" user= "root" password= "123456" >
<readHost host= "Mysql-node2" url= "192.168.10.206:3306" user= "root" password= "123456" >
< /readHost >
< /writeHost >
< /dataHost >
< /mycat :schema>
|
實現主從自動切換的schema.xml配置:即MySQL寫節點宕機後自動切換到備用節點(也就是把從機也配置成writeHosts):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@Mycat-node conf] # vim schema.xml
<?xml version= "1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd" >
<mycat:schema xmlns:mycat= "http://io.mycat/" >
<schema name= "mycat" checkSQLschema= "false" sqlMaxLimit= "100" dataNode= "haha" >
< /schema >
<dataNode name= "haha" dataHost= "Mycat-node" database= "kevin" />
<dataHost name= "Mycat-node" maxCon= "1000" minCon= "10" balance= "1" writeType= "0" dbType= "mysql" dbDriver= "native" switchType= "1" slaveThreshold= "100" >
<heartbeat>show slave status< /heartbeat >
<writeHost host= "Mysql-node1" url= "192.168.10.205:3306" user= "root" password= "123456" >
<readHost host= "Mysql-node2" url= "192.168.10.206:3306" user= "root" password= "123456" >
< /readHost >
< /writeHost >
<writeHost host= "Mysql-node2" url= "192.168.10.206:3306" user= "root" password= "123456" >
< /writeHost >
< /dataHost >
< /mycat :schema>
|
上面配置中,balance改為1,表示讀寫分離。
以上配置達到的效果就是192.168.10.205為主庫,192.168.10.206為從庫。
注意:要保證192.168.10.205和192.168.10.206機器能使用root/123456許可權成功登入mysql資料庫。同時,也一定要授權mycat機器能使用root/123456許可權成功登入這兩臺機器的mysql資料庫!!這很重要,否則會導致登入mycat後,對庫和表操作失敗!
一主一從結構是最簡單的配置。
MyCat支援雙主多從,如果有N個主,那麼就配置N個writeHost兄弟節點;如果有M個從節點,那麼就配置M個readHost節點即可。
也可以有多臺MySQL伺服器,或者SQL Server、Oracle等,配置多個dataHost節點就可以。
需要注意的是:
Mycat主從分離只是在讀的時候做了處理,寫入資料的時候,只會寫入到writehost,需要通過mycat的主從複製將資料複製到readhost!這個問題需要弄明白!!
如果沒有提前做mysql主從複製,會發現Mycat讀寫分離配置後,資料寫入writehost後,readhost一直沒有資料!因為Mycat就沒有實現主從複製的功能,畢竟資料庫本身自帶的這個功能才是最高效穩定的。
特別注意:
1 2 3 4 5 6 7 8 9 10 11 |
1)本案例採用的一主一從模式的兩個mysql例項,並且針對單一的資料庫名進行測試;大多數mycat使用場景都是在多主多從模式並針對多個庫進行的。
2)要想登入Mycat後看到mysql的真實資料庫的表內容,需要在schema.xml檔案中指明database,其中dataNote和dataHost名稱可以自定義,database名稱要是mysql上的庫名。
3)如果針對的是mysql的多個庫,比如mysql的真實庫名是kevin、grace、shanshan,那麼schema.xml檔案裡應該指明多個庫名,如:
<schema name= "mycat" checkSQLschema= "false" sqlMaxLimit= "100" dataNode= "haha,heihei,hengheng" >
< /schema >
<dataNode name= "haha" dataHost= "Mycat-node" database= "kevin" />
<dataNode name= "heihei" dataHost= "Mycat-node" database= "grace" />
<dataNode name= "hengheng" dataHost= "Mycat-node" database= "shanshan" />
........
4)主從自動切換配置後,第一個writeHost故障後,會自動切換到第二個,第二個故障後自動切換到第三個;
如果當是1主3從模式,可以把第1個從節點配置為writeHost 2,第2個和第3個從節點則配置為writeHost 1的readHost;
|
Mycat服務啟動
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
[root@Mycat-node ~] # cd /data/mycat/bin/
[root@Mycat-node bin] #
[root@Mycat-node bin] # ./mycat start #開啟
[root@Mycat-node bin] # ./mycat stop #關閉
[root@Mycat-node bin] # ./mycat restart #重啟
[root@Mycat-node bin] # ./mycat status #檢視啟動狀態
[root@Mycat-node bin] # ./mycat console #前臺執行
[root@Mycat-node bin] # ./mycat pause #暫停
mycat啟動後,執行命令不成功,可能實際上配置有錯誤,導致後面的命令沒有很好的執行。
如果在啟動時發現異常,在logs目錄中檢視日誌。
[root@Mycat-node ~] # cd /data/mycat/logs/
[root@Mycat-node logs] # ls
2018-07 mycat.log mycat.pid wrapper.log
- wrapper.log 為程式啟動的日誌,啟動時的問題看這個
- mycat.log 為指令碼執行時的日誌,SQL指令碼執行報錯後的具體錯誤內容,檢視這個檔案。mycat.log是最新的錯誤日誌,歷史日誌會根據時間生成目錄儲存。
[root@Mycat-node conf] # cd /data/mycat/bin/
[root@Mycat-node bin] # ./mycat start
Starting Mycat-server...
[root@Mycat-node bin] # ps -ef|grep cat
root 5693 1 0 11:28 ? 00:00:00 /data/mycat/bin/ . /wrapper-linux-x86-64 /data/mycat/conf/wrapper .conf wrapper.syslog.ident=mycat wrapper.pidfile= /data/mycat/logs/mycat .pid wrapper.daemonize=TRUE wrapper.lockfile= /var/lock/subsys/mycat
root 5695 5693 58 11:28 ? 00:00:01 java -DMYCAT_HOME=. -server -XX:MaxPermSize=64M -XX:+AggressiveOpts -XX:MaxDirectMemorySize=2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1984 -Dcom.sun.management.jmxremote.authenticate= false -Dcom.sun.management.jmxremote.ssl= false -Xmx4G -Xms1G -Djava.library.path=lib -classpath lib /wrapper .jar:conf:lib /zookeeper-3 .4.6.jar:lib /velocity-1 .7.jar:lib /disruptor-3 .3.4.jar:lib /hamcrest-library-1 .3.jar:lib /curator-client-2 .11.0.jar:lib /mysql-binlog-connector-java-0 .4.1.jar:lib /curator-framework-2 .11.0.jar:lib /wrapper .jar:lib /log4j-1 .2.17.jar:lib /kryo-2 .10.jar:lib /objenesis-1 .2.jar:lib /log4j-core-2 .5.jar:lib /log4j-1 .2-api-2.5.jar:lib /log4j-slf4j-impl-2 .5.jar:lib /leveldb-api-0 .7.jar:lib /minlog-1 .2.jar:lib /mongo-java-driver-2 .11.4.jar:lib /netty-3 .7.0.Final.jar:lib /sequoiadb-driver-1 .12.jar:lib /libwrapper-linux-x86-64 .so:lib /curator-recipes-2 .11.0.jar:lib /dom4j-1 .6.1.jar:lib /commons-lang-2 .6.jar:lib /guava-19 .0.jar:lib /commons-collections-3 .2.1.jar:lib /reflectasm-1 .03.jar:lib /slf4j-api-1 .6.1.jar:lib /joda-time-2 .9.3.jar:lib /jline-0 .9.94.jar:lib /libwrapper-linux-x86-32 .so:lib /leveldb-0 .7.jar:lib /Mycat-server-1 .6-RELEASE.jar:lib /jsr305-2 .0.3.jar:lib /libwrapper-linux-ppc-64 .so:lib /univocity-parsers-2 .2.1.jar:lib /hamcrest-core-1 .3.jar:lib /log4j-api-2 .5.jar:lib /asm-4 .0.jar:lib /mapdb-1 .0.7.jar:lib /fastjson-1 .2.12.jar:lib /druid-1 .0.26.jar:lib /ehcache-core-2 .6.11.jar -Dwrapper.key=ZcN0KgylpD8RMkUx -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=5693 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp io.mycat.MycatStartup start
root 5729 24581 0 11:29 pts /0 00:00:00 grep cat
Mycat服務埠預設是8066
[root@Mycat-node bin] # lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
java 5695 root 79u IPv6 37036522 0t0 TCP *:8066 (LISTEN)[root@Mycat-node conf] # lsof -i:9066
Mycat還有一個管理埠,預設是9066
[root@Mycat-node conf] # lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
java 5695 root 75u IPv6 37036520 0t0 TCP *:9066 (LISTEN)
|
在客戶機遠端登入Mycat登入mysql(將mycat啟動起來後,遠端連線,預設埠是8066,邏輯庫名和賬號密碼就是在schema.xml裡配置的資訊。程式碼裡用jdbc方式連線)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
Mycat帶來的最大好處就是:
使用是完全不用修改原有程式碼的,在mycat通過命令啟動後,你只需要將資料庫連線切換到Mycat的地址就可以了。
如下面就可以進行連線了(注意使用server.xml檔案中定義的使用者名稱和密碼連線mycat)
登入mycat的前提是:兩臺mysql機器要授權mycat伺服器使用root /123456 成功登入這兩個mysql。
[root@client-server ~] # mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and /or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and /or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row in set (0.01 sec)
mysql> use mycat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows in set (0.00 sec)
mysql>
|
Mycat讀寫分離測試
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
將mycat的日誌輸出級別改完debug(預設是info級別),在conf /log4j2 .xml裡配置,然後去查詢去新增資料在 /logs/mycat .log日誌檔案裡檢視sql被路由到了
哪個伺服器上
特別注意:查詢語句不要加事務,否則讀操作會被分發到寫伺服器上。
[root@Mycat-node ~] # vim /data/mycat/conf/log4j2.xml
......
把
<asyncRoot level= "info" includeLocation= "true" >
改成
<asyncRoot level= "debug" includeLocation= "true" >
重啟mycat服務
[root@Mycat-node ~] # /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node ~] # lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
java 18955 root 79u IPv6 3812293 0t0 TCP *:8066 (LISTEN)
登入mycat
[root@client-server ~] # mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and /or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and /or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row in set (0.00 sec)
mysql> use mycat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
+----+-------------+
3 rows in set (0.00 sec)
mysql>
通過mycat寫入一條資料或讀資料,檢視sql被路由到了代理的哪個mysql伺服器上了:
mysql> insert into kevin.haha values(4, "lihuan" );
Query OK, 1 row affected (0.31 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows in set (0.01 sec)
mysql>
然後檢視mycat.log的debug日誌,觀察mysql的sql被路由到了哪個伺服器上了(下面日誌中的192.168.10.203是遠端客戶機的ip地址)。
[root@Mycat-node ~] # tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 08:50:12.616 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:110)) - ServerConnection
[ id =2, schema=mycat, host=192.168.10.203, user=bobo,txIsolation=3, autocommit= true , schema=mycat]insert into kevin.haha values(4, "lihuan" ),
route={
1 -> haha{insert into kevin.haha values(4, "lihuan" )}
.......
.......
2018-07-31 08:50:12.617 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) -
con need syn ,total syn cmd 1 commands SET names latin1;schema change: false con:MySQLConnection [ id =6, lastTime=1532998212617, user=root,
schema=kevin, old shema=kevin, borrowed= true , fromSlaveDB= false , threadId=55, charset=latin1, txIsolation=3, autocommit= true , attachment=
haha{insert into kevin.haha values(4, "lihuan" )}, respHandler=SingleNodeHandler [node=haha{insert into kevin.haha values(4, "lihuan" )}, packetId=0],
host=192.168.10.205, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted= true ]
.......
.......
2018-07-31 08:50:14.358 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [ id =12, lastTime=1532998214353, user=root, schema=kevin, old shema=kevin, borrowed= true , fromSlaveDB= true ,
threadId=29, charset=latin1, txIsolation=3, autocommit= true , attachment=haha{ select * from haha}, respHandler=SingleNodeHandler [node=haha
{ select * from haha}, packetId=8], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted= false ]
從日誌中可以看出, "insert into ...." 插入語句路由到了192.168.10.205的主機上了, "select * ..." 的查詢語句路由到了192.168.10.206的從機上了。
這就實現了mysql的讀寫分離!!
|
Mycat主從自動切換測試(採用上面自動切換的schema.xml配置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
首先關閉主機192.168.10.205的mysql服務,此時從機192.168.10.206的mysql已經失去了和主機192.168.10.205的mysql主從關係。
[root@Mysql-node1 ~] # /etc/init.d/mysql stop
Shutting down MySQL............ SUCCESS!
[root@Mysql-node1 ~] # lsof -i:3306
[root@Mysql-node1 ~] #
[root@Mysql-node2 ~] # mysql -p123456
........
mysql> show slave status \G;
*************************** 1. row ***************************
.......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
.......
Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry- time : 60 retries: 1
然後客戶機登入mycat進行讀寫操作
[root@client-server ~] # mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
......
mysql> use mycat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows in set (0.00 sec)
mysql> insert into kevin.haha values(5, "gengmei" );
Query OK, 1 row affected (0.00 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows in set (0.00 sec)
同時檢視mycat.log的debug日誌,觀察讀寫操作都被路由到哪裡了:
[root@Mycat-node ~] # tail -f /data/mycat/logs/mycat.log
.......
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.net.AbstractConnection.close(AbstractConnection.java:508)) - close connection,reason:java.net.
ConnectException: Connection refused ,MySQLConnection [ id =0, lastTime=1532999419254, user=root, schema=kevin, old shema=kevin, borrowed= false , fromSlaveDB= false ,
threadId=0, charset=utf8, txIsolation=3, autocommit= true , attachment=null, respHandler=null, host=192.168.10.205, port=3306, statusSync=null, writeQueue=0,
modifiedSQLExecuted= false ]
2018-07-31 09:10:19.261 INFO [$_NIOConnector] (io.mycat.sqlengine.SQLJob.connectionError(SQLJob.java:114)) - can't get connection for sql :show slave status
.......
2018-07-31 09:06:20.139 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [ id =17, lastTime=1532999180134, user=root, schema=kevin, old shema=kevin, borrowed= true , fromSlaveDB= false ,
threadId=46, charset=latin1, txIsolation=3, autocommit= true , attachment=haha{insert into kevin.haha values(5, "gengmei" )}, respHandler=SingleNodeHandler
[node=haha{insert into kevin.haha values(5, "gengmei" )}, packetId=1], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted= true ]
......
2018-07-31 09:06:21.727 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.MySQLConnection.synAndDoExecute(MySQLConnection.java:448)) - con need syn ,total
syn cmd 1 commands SET names latin1;schema change: false con:MySQLConnection [ id =16, lastTime=1532999181727, user=root, schema=kevin, old shema=kevin, borrowed
= true , fromSlaveDB= false , threadId=48, charset=latin1, txIsolation=3, autocommit= true , attachment=haha{ select * from haha}, respHandler=SingleNodeHandler [node=
haha{ select * from haha}, packetId=0], host=192.168.10.206, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted= false ]
從上面的日誌中可以看出,主機192.168.10.205已經斷開從mycat連線,insert寫語句和 select 讀語句都被路由分配到了從機192.168.10.206的mysql上了,
這就看出來已經實現了mysql主從啟動切換了!!!
登入從機192.168.10.206的mysql,發現新插入的資料已經寫進去了
[root@Mysql-node2 ~] # mysql -p123456
.......
mysql> use kevin;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from kevin.haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 5 | gengmei |
+----+-------------+
5 rows in set (0.00 sec)
mysql>
|
Mycat分表分庫的原理
mycat裡面通過定義路由規則來實現分片表(路由規則裡面會定義分片欄位,以及分片演算法)。分片演算法有多種,你所說的hash是其中一種,還有取模、按範圍分片等等。在mycat裡面,會對所有傳遞的sql語句做路由處理(路由處理的依據就是表是否分片,如果分片,那麼需要依據分片欄位和對應的分片演算法來判斷sql應該傳遞到哪一個、或者哪幾個、又或者全部節點去執行)
Mycat適用於哪些場景?
資料量大到單機hold不住,而又不希望調整架構切換為NoSQL資料庫,這個場景下可以考慮適用mycat。當然,使用前也應該做規劃,哪些表需要分片等等。另外mycat對跨庫join的支援不是很好,在使用mycat的時候要注意規避這種場景。
應用場景2--->MYcat分庫分表配置及測試:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
接著上面的操作繼續:
啟動主機192.168.10.205的mysql
[root@Mysql-node1 ~] # /etc/init.d/mysql start
Starting MySQL... SUCCESS!
[root@Mysql-node1 ~] # lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
mysqld 11645 mysql 17u IPv4 10457025 0t0 TCP *:mysql (LISTEN)
mysqld 11645 mysql 39u IPv4 10457749 0t0 TCP Mysql-node1:mysql->Mycat-node:39252 (ESTABLISHED)
mysqld 11645 mysql 40u IPv4 10458099 0t0 TCP Mysql-node1:mysql->Mysql-node1:57270 (ESTABLISHED)
登入從機192.168.10.206的mysql,重啟slave的主從同步關係
[root@Mysql-node2 ~] # mysql -p123456
......
mysql> show slave status \G;
......
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
......
Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry- time : 60 retries: 81
......
mysql> stop slave;
Query OK, 0 rows affected (0.08 sec)
mysql> start slave;
Query OK, 0 rows affected (0.04 sec)
mysql> show slave status \G;
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
.....
在主機192.168.10.205的mysql上再建立一個數據庫grace
現在需要將haha表放在kevin庫裡,將heihei表拆分放到kevin和grace庫了。
操作如下(在主機mysql裡操作,從機mysql自動會同步過來):
登入grace庫裡建立heihei表,同時在kevin庫裡也建立heihei表。
特別需要注意的是:
- 分表的表在建立時一定要建立主鍵,否則在mycat端寫入資料時會報錯主鍵衝突!!
- 分表的表要在兩個庫上都要建立。
mysql> CREATE DATABASE grace CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> use grace;
Database changed
mysql> CREATE TABLE heihei (
-> id INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY ( id )
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> insert into grace.heihei values(1, "beijing" );
Query OK, 1 row affected (0.03 sec)
mysql> show tables;
+-----------------+
| Tables_in_grace |
+-----------------+
| heihei |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from grace.heihei;
+----+---------+
| id | name |
+----+---------+
| 1 | beijing |
+----+---------+
1 row in set (0.00 sec)
mysql> use kevin;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
+-----------------+
1 row in set (0.00 sec)
mysql> CREATE TABLE heihei (
-> id INT NOT NULL AUTO_INCREMENT,
-> city varchar(50) NOT NULL,
-> PRIMARY KEY ( id )
-> )AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.23 sec)
mysql> show tables;
+-----------------+
| Tables_in_kevin |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows in set (0.00 sec)
mysql> insert into kevin.heihei values(1, "shanghai" );
Query OK, 1 row affected (0.13 sec)
mysql> select * from kevin.heihei;
+----+----------+
| id | name |
+----+----------+
| 1 | shanghai |
+----+----------+
1 row in set (0.00 sec)
上面在從機的mysql裡操作後,從機的mysql會自動把資料同步過來!
登入mycat機器192.168.10.210機器,分別設定server.xml檔案、rule.xml檔案、schema.xml檔案
server.xml檔案在上面已經設定過了,這裡就不用修改了:
[root@Mycat-node ~] # vim /data/mycat/conf/server.xml
......
<!-- mycat的服務埠預設為8066,管理埠預設為9066 -->
<property name= "serverPort" >8066< /property > <property name= "managerPort" >9066< /property >
.....
<!-- 任意設定登陸 mycat 的使用者名稱,密碼,資料庫 -->
<user name= "bobo" >
<property name= "password" >bo@123< /property >
<property name= "schemas" >mycat< /property >
<!-- 表級 DML 許可權設定 -->
<!--
<privileges check= "false" >
<schema name= "TESTDB" dml= "0110" >
<table name= "tb01" dml= "0000" >< /table >
<table name= "tb02" dml= "1111" >< /table >
< /schema >
< /privileges >
-->
< /user >
<!--
<user name= "user" >
<property name= "password" >user< /property >
<property name= "schemas" >TESTDB< /property >
<property name= "readOnly" > true < /property >
< /user >
-->
< /mycat :server>
分庫分表配置還涉及到rule.xml檔案,配置如下(備份檔案,清空,直接複製下面內容):
[root@Mycat-node conf] # cp rule.xml rule.xml.bak
[root@Mycat-node conf] # vim rule.xml
<?xml version= "1.0" encoding= "UTF-8" ?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License" );
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http: //www .apache.org /licenses/LICENSE-2 .0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:rule SYSTEM "rule.dtd" >
<mycat:rule xmlns:mycat= "http://io.mycat/" >
<tableRule name= "mycat-rule" > <!-- heihei表分片的規則名,這裡定義為mycat-rule,這個需要在schema.xml檔案中引用 -->
<rule>
<columns> id < /columns > <!--heihei表的分片列 -->
<algorithm>mod-long< /algorithm >
< /rule >
< /tableRule >
< function name= "mod-long" class= "io.mycat.route.function.PartitionByMod" >
<!-- how many data nodes -->
<property name= "count" >2< /property > <!-- count值與分片個數相同,這裡heihei表分片到kevin庫和grace庫裡,共2份。 -->
< /function >
< /mycat :rule>
接著配置schema.xml檔案(server.xml檔案配置在已經已經完成),分庫分表配置如下
(要將rule.xml裡定義的分片模型寫進去,由於這裡的heihei表配置了主鍵,所以primaryKey= "id" 這個也寫進去,其他情況看錶結構,也可以不寫):
[root@Mycat-node conf] # cp schema.xml schema.xml.old
[root@Mycat-node conf] # vim schema.xml
<?xml version= "1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd" >
<mycat:schema xmlns:mycat= "http://io.mycat/" >
<schema name= "mycat" checkSQLschema= "false" sqlMaxLimit= "100" >
<table name= "haha" primaryKey= "id" dataNode= "kevin_db" />
<table name= "heihei" primaryKey= "id" dataNode= "kevin_db,grace_db" rule= "mycat-rule" />
< /schema >
<dataNode name= "kevin_db" dataHost= "Mycat-node" database= "kevin" />
<dataNode name= "grace_db" dataHost= "Mycat-node" database= "grace" />
<dataHost name= "Mycat-node" maxCon= "1000" minCon= "10" balance= "1" writeType= "0" dbType= "mysql" dbDriver= "native" switchType= "1" slaveThreshold= "100" >
<heartbeat>show slave status< /heartbeat >
<writeHost host= "Mysql-node1" url= "192.168.10.205:3306" user= "root" password= "123456" >
<readHost host= "Mysql-node2" url= "192.168.10.206:3306" user= "root" password= "123456" >
< /readHost >
< /writeHost >
<writeHost host= "Mysql-node1" url= "192.168.10.206:3306" user= "root" password= "123456" >
< /writeHost >
< /dataHost >
< /mycat :schema>
重啟mycat服務
[root@Mycat-node conf] # /data/mycat/bin/mycat restart
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...
[root@Mycat-node conf] # lsof -i:8066
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
java 971 root 79u IPv6 4024290 0t0 TCP *:8066 (LISTEN)
[root@Mycat-node conf] # lsof -i:9066
COMMAND PID USER FD TYPE DEVICE SIZE /OFF NODE NAME
java 971 root 75u IPv6 4024288 0t0 TCP *:9066 (LISTEN)
在客戶機遠端登入Mycat
[root@client-server ~] # mysql -h192.168.10.210 -P8066 -ubobo -pbo@123
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2013, Oracle and /or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and /or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat |
+----------+
1 row in set (0.01 sec)
mysql> use mycat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables in mycat |
+-----------------+
| haha |
| heihei |
+-----------------+
2 rows in set (0.01 sec)
mysql> select * from haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
+----+-------------+
4 rows in set (0.12 sec)
mysql> select * from heihei;
+----+----------+
| id | city |
+----+----------+
| 1 | beijing |
| 1 | shanghai |
+----+----------+
2 rows in set (0.04 sec)
mysql>
分別在mycat裡往heihei和grace.heihei表裡插入一些資料
mysql> insert into haha values(10, "wangbiao" );
insert into haha values(11, "zhangcaiyi" );Query OK, 1 row affected (0.06 sec)
mysql> insert into haha values(11, "zhangcaiyi" );
Query OK, 1 row affected (0.06 sec)
mysql> insert into heihei( id ,city) values(20, "chognqing" );
Query OK, 1 row affected (0.09 sec)
mysql> insert into heihei( id ,city) values(22, "xianggang" );
insert into heihei( id ,city) values(28, "chengdu" );Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei( id ,city) values(23, "huoqiu" );
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei( id ,city) values(24, "haikou" );
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei( id ,city) values(25, "anqing" );
Query OK, 1 row affected (0.03 sec)
mysql> insert into heihei( id ,city) values(26, "tianqing" );
Query OK, 1 row affected (0.02 sec)
mysql> insert into heihei( id ,city) values(27, "hangzhou" );
Query OK, 1 row affected (0.04 sec)
mysql> insert into heihei( id ,city) values(28, "chengdu" );
Query OK, 1 row affected (0.26 sec)
特別注意:
1)在配置了sharding分片策略之後(如heihei表),mycat裡分片的表做插入資料時,即使插入所有欄位的資料,也一定要在表名後面寫明插入資料的欄位名稱,
否則插入資料會報錯:ERROR 1064 (HY000): partition table, insert must provide ColumnList
2)沒有配置sharding分片策略的表(如haha表),插入所有欄位的資料時,表名後面不需要寫明欄位名稱,預設就是所有欄位插入資料,如上面的haha表。
登入主機和從機,檢視從mycat端寫入的資料
mysql> select * from kevin.haha;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wangshibo |
| 2 | linan |
| 3 | zhangminmin |
| 4 | lihuan |
| 10 | wangbiao |
| 11 | zhangcaiyi |
+----+-------------+
6 rows in set (0.00 sec)
mysql> select * from grace.heihei;
+----+-----------+
| id | city |
+----+-----------+
| 1 | beijing |
| 21 | guangzhou |
| 23 | huoqiu |
| 25 | anqing |
| 27 | hangzhou |
+----+-----------+
5 rows in set (0.00 sec)
mysql> select * from kevin.heihei;
+----+-----------+
| id | city |
+----+-----------+
| 1 | shanghai |
| 20 | chognqing |
| 22 | xianggang |
| 24 | haikou |
| 26 | tianqing |
| 28 | chengdu |
+----+-----------+
6 rows in set (0.00 sec)
mysql>
從上面可以看出:
在mycat裡往做了sharding分片策略的heihei表裡寫入的資料,已經分片到kevin和grace兩個庫裡了,即成功實現了分庫分表功能!
檢視mycat的debug日誌,可以觀察到mysql讀寫分離和分庫分表情況
[root@Mycat-node logs] # tail -f mycat.log
|
這裡需要注意:
-查詢語句不要加事務,否則讀操作會被分發到寫伺服器上。
-主從複製是mysql自己實現的,mycat只是代理外掛,它本身不能實現主從複製,只能實現了讀寫分離、主從切換、分庫分表功能。
為了提升查詢的效能,有人創新的設計了一種MySQL主從複製的模式,主節點為InnoDB引擎,讀節點為MyISAM引擎,經過實踐,發現查詢效能提升不少。
此外,為了減少主從複製的時延,也建議採用MySQL 5.6+的版本,用GTID同步複製方式減少複製的時延,可以將一個Database中的表,根據寫頻率的不同,
分割成幾個Database,用Mycat虛擬為一個Database,這樣就滿足了多庫併發複製的優勢,需要注意的是,要將有Join關係的表放在同一個庫中。
對於某些表,要求不能有複製時延,則可以考慮這些表放到Gluster叢集裡,消除同步複製的時延問題,前提是這些表的修改操作並不很頻繁,需要做效能測試,
以確保能滿足業務高峰。
總結一下,Mycat做讀寫分離和高可用,可能的方案很靈活,只有你沒想到的,沒有做不到的。
=================Mycat常見問題及注意點==================
1)Mycat自動切換需要人工處理麼?
Mycat通過心跳檢測,自主切換資料庫,保證高可用性,無須手動切換。
2)Mycat支援叢集麼?
目前Mycat沒有實現對多Mycat叢集的支援,可以暫時使用haproxy來做負載,或者統計硬體負載。
3)Mycat目前有生產案例了麼?
目前Mycat初步統計大概600家公司使用。
4)Mycat穩定性與Cobar如何?
目前Mycat穩定性優於Cobar,而且一直在更新,Cobar已經停止維護,可以放心使用。
5)Mycat除了Mysql還支援哪些資料庫?
mongodb、oracle、sqlserver 、hive 、db2 、 postgresql。
6)Mycat如何配置字符集?
在配置檔案server.xml配置,預設配置為utf8。
7)Mycat後臺管理監控如何使用?
9066埠可以用JDBC方式執行命令,在介面上進行管理維護,也可以通過命令列檢視命令列操作。
命令列操作是:mysql -h127.0.0.1 -utest -ptest -P9066 登陸,然後執行相應命令。
8)Mycat主鍵插入後應用如何獲取?
獲得自增主鍵,插入記錄後執行select last_insert_id()獲取。
9)Mycat執行sql時經常阻塞或卡死是什麼原因?
如果出現執行sql語句長時間未返回,或卡死,請檢查是否是虛機下執行或cpu為單核。如果仍舊無法解決,可以暫時跳過,目前有些環境阻塞卡死原因未知。
10)Mycat中,舊系統資料如何遷移到Mycat中?
舊資料遷移目前可以手工匯入,在mycat中提取配置好分配規則及後端分片資料庫,然後通過dump或loaddata方式匯入,後續Mycat就做舊資料自動資料遷移工具。
11)Mycat如何對舊分片資料遷移或擴容,支援自動擴容麼?
目前除了一致性hash規則分片外其他資料遷移比較困難,目前暫時可以手工遷移,未提供自動遷移方案,具體遷移方案情況Mycat權威指南對應章節。
12)Mycat支援批量插入嗎?
目前Mycat1.3.0.3以後支援多values的批量插入,如insert into(xxx) values(xxx),(xxx) 。
13)Mycat支援多表Join嗎?
Mycat目前支援2個表Join,後續會支援多表Join,具體Join請看Mycat權威指南對應章節。
14)Mycat 啟動報主機不存在的問題?
需要新增ip跟主機的對映。
15)Mycat連線會報無效資料來源(Invalid datasource)?
例如報錯:mysql> select * from company;
ERROR 3009 (HY000): java.lang.IllegalArgumentException: Invalid DataSource:0
這類錯誤最常見是一些配置問題例如schema.xml中的dataNode的配置和實際不符合,請先仔細檢查配置項,確保配置沒有問題。
如果不是配置問題,分析具體日誌看出錯原因,常見的有:
- 如果是應用連:在某些版本的Mysql驅動下連線Mycat會報錯,可升級最新的驅動包試下。
- 如果是服務端控制檯連,確認mysql是否開啟遠端連線許可權,或防火牆是否設定正確,或者資料庫database是否配置,或使用者名稱密碼是否正確。
16)Mycat支援的或者不支援的語句有哪些?
insert into,複雜子查詢,3表及其以上跨庫join等不支援。
17)MycatJDBC連線報 PacketTooBigException異常
檢查mysqljdbc驅動的版本,在使用mycat1.3和mycat1.4版本情況下,不要使用jdbc5.1.37和38版本的驅動,會出現如下異常報錯:
com.mysql.jdbc.PacketTooBigException: Packet for query is too large (60 > -1). You can change this value on the server by setting the max_allowed_packet’ variable。
建議使用jdbc5.1.35或者36的版本。
18)Mycat中文亂碼的問題
答:如果在使用mycat出現中文插入或者查詢出現亂碼,請檢查三個環節的字符集設定:
a)客戶端環節(應用程式、mysql命令或圖形終端工具)連線mycat字符集
b)mycat連線資料庫的字符集
c)資料庫(mysql,oracle)字符集。這三個環節的字符集如果配置一致,則不會出現中文亂碼,其中尤其需要注意的是客戶端連線mycat時使用的連線字符集,
通常的中文亂碼問題一般都由此處設定不當引出。其中mycat內部預設使用utf8字符集,在最初啟動連線資料庫時,mycat會預設使用utf8去連線資料庫,當客戶
端真正連線mycat訪問資料庫時,mycat會使用客戶端連線使用的字符集修改它連線資料庫的字符集,在mycat環境的管理9066埠,可以通過"show @@backend"命令
檢視後端資料庫的連線字符集,通過show @@connection命令檢視前端客戶端的連線字符集。客戶端的連線可以通過指定字符集編碼或者傳送SET命令指定連線mycat
時connection使用的字符集,常見客戶端連線指定字符集寫法如下:
- jdbcUrl=jdbc:mysql://localhost:8066/databaseName? characterEncoding=iso_1
- SET character_set_client = utf8;用來指定解析客戶端傳遞資料的編碼
SET character_set_results = utf8;用來指定資料庫內部處理時使用的編碼
SET character_set_connection = utf8;用來指定資料返回給客戶端的編碼方式
- mysql –utest –ptest –P8066 –default-character-set=gbk
19)Mycat無法登陸Access denied
Mycat正常安裝配置完成,登陸mycat出現以下錯誤:
[mysql@master ~]$ mysql -utest -ptest -P8066
ERROR 1045 (28000): Access denied for user 'test’@’localhost’ (using password: YES)
請檢查在schema.xml中的相關dataHost的mysql主機的登陸許可權,一般都是因為配置的mysql的使用者登陸許可權不符合,mysql使用者許可權管理不熟悉的請自己度娘。
只有一種情況例外,mycat和mysql主機都部署在同一臺裝置,其中主機localhost的許可權配置正確,使用-hlocalhost能正確登陸mysql但是無法登陸mycat的情況,
請使用-h127.0.0.1登陸,或者本地網路實際地址,不要使用-hlocalhost,很多使用者反饋此問題,原因未明。
20)Mycat的分片資料插入報異常IndexOutofBoundException
在一些配置了分片策略的表進行資料插入時報錯,常見的報錯資訊如下:java.lang.IndexOutOfBoundsException:Index:4,size:3
這類報錯通常由於分片策略配置不對引起,請仔細檢查並理解分片策略的配置,例如:使用固定分片hash演算法,PartitionByLong策略,如果schema.xml裡面設定
的分片數量dataNode和rule.xml配置的partitionCount 分片個數不一致,尤其是出現分片數量dataNode小於partitionCount數量的情況,插入資料就可能會報錯。
很多使用者都沒有仔細理解文件中對分片策略的說明,用預設rule.xml配置的值,沒有和自己實際使用環境進行引數核實就進行分片策略使用造成這類問題居多。
21)Mycat ER分片子表資料插入報錯
一般都是插入子表時出現不能找到父節點的報錯。報錯資訊如: [Err] 1064 - can’t find (root) parent sharding node for sql:。
此類ER表的插入操作不能做為一個事務進行資料提交,如果父子表在一個事務中進行提交,顯然在事務沒有提交前子表是無法查到父表的資料的,因此就無法確定
sharding node。如果是ER關係的表在插入資料時不能在同一個事務中提交資料,只能分開提交。
22)Mycat最大記憶體無法調整至4G以上
mycat1.4的JVM使用最大記憶體調整如果超過4G大小,不能使用wrapper.java.maxmemory引數,需要使用wrapper.java.additional的寫法,注意將
wrapper.java.maxmemory引數註釋,例如增加最大記憶體至8G:wrapper.java.additional.10=-Xmx8G。
23)Mycat使用過程中報錯怎麼辦
記住無論什麼時候遇到報錯,如果不能第一時間理解報錯的原因,首先就去看日誌,無論是啟動(wrapper.log)還是執行過程中(mycat.log),請相信良好的
日誌是程式設計查錯的終極必殺技。日誌如果記錄資訊不夠,可以調整conf/log4j.xml中的level級別至debug,所有的詳細資訊均會記錄。另外如果在群裡面提問,
儘量將環境配置資訊和報錯日誌提供清楚,這樣別人才能快速幫你定位問題。