使用mysql federated引擎構建MySQL分布式數據庫訪問層
本文所描述的 federated屬於 MySQL的一種特殊引擎,利用它可將本地數據表映射至遠程 MySQL 數據表,從而就可以解決應用程序中繁多的跨機器連接數據庫問題,拓撲圖如下:
如此就可以構造出一個統一的數據訪問入口,就大大提高了整個數據庫系統的可維護性。 Federated引擎是基於表級別的,只能將本地數據表定義為 Federated 引擎並映射至遠程實體表,無法實現基於庫級別的整體映射。
在本文中,我們將啟用Federated 引擎的數據庫訪問入口服務器稱為本地數據庫,而將本地數據表對應的遠程數據表,稱之為實體表。
本地數據庫需要啟用Federated 引擎支持,而遠程數據表無須 Federated 引擎支持。 Federated 引擎表使用標准的 MySQL 客戶端協議與遠程數據庫建立 TCP 連接。
創建Federated 表的過程:
以root 登錄遠程 MySQL ,上創建合適的訪問賬號 grant all on DB1.* to 'federated'@'%' identified by 'federated'; flush privileges;
在遠程MySQL 找到對應實體表的創建命令(如果是新表,請先建立好數據表,再執行此命令) 假設在遠程mysql 上有庫名 DB1, 表名 tag, 執行以下命令找到遠程表的結構: show create table DB1.tag 輸出: CREATE TABLE tag ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(128) NOT NULL, frequency int(10) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (id) ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
假設我們要將遠程的DB1.tag 映射至本地 DB.TableA 表上。那麼我們應該保持本地虛擬表與遠程實體表結構一致(結構可以有所差異,但會造成使用,管理上的麻煩)。根據遠程實體表的創建命令,創建本地虛擬表 ( 結構部分完全一樣,創建表選項有所差異 ) :
登錄本地Mysql 服務器,創建相應的數據庫及表: create database DB; use DB; CREATE TABLE TableA ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(128) NOT NULL, frequency int(10) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (id) ) ENGINE=federated connection="mysql://federated:[email protected] :3306/DB1/tag";
這時,即建立好了federated 虛擬表,實際上本地 MySQL 只創建了表定義文件 , 而沒有數據文件。我們對本地虛擬表的數據修改,均會發送到遠程機器上執行。
本地虛擬表名與遠程表名,可不相同。
經過測試,這個引擎的一些額外特點: 1. 本地虛擬表與遠程實體表之間是 TCP 長連接,並且是多個客戶端利用的。所以不用擔心因頻繁建立連接帶來的網絡開銷。 2. 本虛擬表表與遠程實體表之間的網絡連接斷開後,當對虛擬表發起查詢時,它會嘗試重新連接遠程實體表,所以我們不用擔心網絡連接斷開造成的永久中斷問題。 3. 如果無時間未對本地虛擬表作任何操作,虛擬表與實體表之間的連接將在遠程主機的 wait_timeout 秒後自動斷開,當對虛擬表發起查詢時,連接又會重新建立。
一些注意事項: 1. 對本地虛擬表的結構修改,並不會修改遠程表的結構 2. truncate 命令,會清除遠程表數據 3. drop命令只會刪除虛擬表,並不會刪除遠程表 4. 不支持 alter table 命令 目前使用federated 最大的缺點: 1. select count(*), select * from limit M, N 等語句執行效率非常低,數據量較大時存在很嚴重的問題,但是按主鍵或索引列查詢,則很快,如以下查詢就非常慢(假設 id 為主索引) select id from db.tablea where id >100 limit 10 ; 而以下查詢就很快: select id from db.tablea where id >100 and id<150
如果虛擬虛擬表中字段未建立索引,而實體表中為此字段建立了索引,此種情況下,性能也相當差。但是當給虛擬表建立索引後,性能恢復正常。
類似 where name like "str%" limit 1 的查詢,即使在 name 列上創建了索引,也會導致查詢過慢,是因為 federated引擎會將所有滿足條件的記錄讀取到本,再進行 limit 處理。
這幾個問題已經嚴重影響了federated 在實際環境中的應用。