[Mysql] 關於 Innodb 和 NDB 的一些事

作爲一個準 PHPer,今天必須要寫的第一句話一定是: Happy birthday to PHP ~ 第十五個年頭了,PHP 發展至今仍然能佔據最流行語言 TOP4 的位置,確實令不少人驚異不已,但是這就是 PHP 獨特的魅力,真心希望他能更好的發展下去,期待 PHP6 給我們帶來驚喜;順便查了一下 PHP 的好夥伴 Mysql 的生日,讓我喫驚的是今年他居然已經 31 歲了,呵呵~ 真是老當益壯啊~ 好吧,今天就來說說 Mysql 的一些 “八卦” 吧~

 

對於目前的 Mysql 的境遇來說,真可謂是命運多舛,但是他的功能之強大家應該都深有體會了吧,其實我一直認爲 PHP 能有今天的地位,Mysql 這位 “老大哥” 的支持絕對功不可沒~ 而 Innodb 應該算是 Mysql Engine 龐大的家族中最令人稱道的主力軍了吧,目前估計 80% 的 Mysql 服務器應該都在用,支持事務是 Innodb 的最大特點,其他的事就先不介紹了。以下收集了 Innodb 配置參數的詳細解釋,我想應該對大家比較有幫助:

 

innodb_data_home_dir

這是InnoDB表的目錄共用設置。如果沒有在 my.cnf 進行設置,InnoDB 將使用MySQL的 datadir 目錄爲缺省目錄。如果設定一個空字串,可以在 innodb_data_file_path 中設定絕對路徑。

innodb_data_file_path

單獨指定數據文件的路徑與大小。數據文件的完整路徑由 innodb_data_home_dir 與這裏所設定值的組合。 文件大小以 MB 單位指定。因此在文件大小指定後必有“M”。 InnoDB 也支持縮寫“G”, 1G = 1024M。從 3.23.44 開始,在那些支持大文件的操作系統上可以設置數據文件大小大於 4 GB。而在另一些操作系統上數據文件必須小於 2 GB。數據文件大小總和至少要達到 10 MB。在 MySQL-3.23 中這個參數必須在 my.cnf 中明確指定。在 MySQL-4.0.2 以及更新版本中則不需如此,系統會默認在 MySQL 的 datadir 目錄下創建一個 16 MB 自擴充(auto-extending)的數據文件 ibdata1。你同樣可以使用一個 原生磁盤分區(RAW raw disk partitions(raw devices)) 作爲數據文件, 如何在 my.cnf 中詳細指定它們請查看第 12.1 節。

innodb_mirrored_log_groups

爲了保護數據而設置的日誌文件組的拷貝數目,默認設置爲 1。在 my.cnf 中以數字格式設置。

innodb_log_group_home_dir

InnoDB 日誌文件的路徑。必須與 innodb_log_arch_dir 設置相同值。 如果沒有明確指定將默認在 MySQL 的 datadir 目錄下建立兩個 5 MB 大小的 ib_logfile... 文件。

innodb_log_files_in_group

日誌組中的日誌文件數目。InnoDB 以環型方式(circular fashion)寫入文件。數值 3 被推薦使用。在 my.cnf 中以數字格式設置。

innodb_log_file_size

日誌組中的每個日誌文件的大小(單位 MB)。如果 n 是日誌組中日誌文件的數目,那麼理想的數值爲 1M 至下面設置的緩衝池(buffer pool)大小的 1/n。較大的值,可以減少刷新緩衝池的次數,從而減少磁盤 I/O。但是大的日誌文件意味着在崩潰時需要更長的時間來恢復數據。 日誌文件總和必須小於 2 GB,3.23.55 和 4.0.9 以上爲小於 4 GB。在 my.cnf 中以數字格式設置。

innodb_log_buffer_size

InnoDB 將日誌寫入日誌磁盤文件前的緩衝大小。理想值爲 1M 至 8M。大的日誌緩衝允許事務運行時不需要將日誌保存入磁盤而只到事務被提交(commit)。 因此,如果有大的事務處理,設置大的日誌緩衝可以減少磁盤I/O。 在 my.cnf 中以數字格式設置。

innodb_flush_log_at_trx_commit

通常設置爲 1,意味着在事務提交前日誌已被寫入磁盤, 事務可以運行更長以及服務崩潰後的修復能力。如果你願意減弱這個安全,或你運行的是比較小的事務處理,可以將它設置爲 0 ,以減少寫日誌文件的磁盤 I/O。這個選項默認設置爲 0。

innodb_log_arch_dir

The directory where fully written log files would be archived if we used log archiving. 這裏設置的參數必須與 innodb_log_group_home_dir 相同。 從 4.0.6 開始,可以忽略這個參數。

innodb_log_archive

這 個值通常設爲 0。 既然從備份中恢復(recovery)適合於 MySQL 使用它自己的 log files,因而通常不再需要 archive InnoDB log files。這個選項默認設置爲 0。

innodb_buffer_pool_size

InnoDB 用來高速緩衝數據和索引內存緩衝大小。 更大的設置可以使訪問數據時減少磁盤 I/O。在一個專用的數據庫服務器上可以將它設置爲物理內存的 80 %。 不要將它設置太大,因爲物理內存的使用競爭可能會影響操作系統的頁面調用。在 my.cnf 中以數字格式設置。

innodb_additional_mem_pool_size

InnoDB 用來存儲數據字典(data dictionary)信息和其它內部數據結構(internal data structures)的存儲器組合(memory pool)大小。理想的值爲 2M,如果有更多的表你就需要在這裏重新分配。如果 InnoDB 用盡這個池中的所有內存,它將從操作系統中分配內存,並將錯誤信息寫入 MySQL 的錯誤日誌中。在 my.cnf 中以數字格式設置。

innodb_file_io_threads

InnoDB 中的文件 I/O 線程。 通常設置爲 4,但是在 Windows 下可以設定一個更大的值以提高磁盤 I/O。在 my.cnf 中以數字格式設置。

innodb_lock_wait_timeout

在回滾(rooled back)之前,InnoDB 事務將等待超時的時間(單位 秒)。InnoDB 會自動檢查自身在鎖定表與事務回滾時的事務死鎖。如果使用 LOCK TABLES 命令,或在同一個事務中使用其它事務安全型表處理器(transaction safe table handlers than InnoDB),那麼可能會發生一個 InnoDB 無法注意到的死鎖。在這種情況下超時將用來解決這個問題。這個參數的默認值爲 50 秒。在 my.cnf 中以數字格式設置。

innodb_flush_method

這個參數僅僅與 Unix 相關。這個參數默認值爲 fdatasync。 另一個設置項爲 O_DSYNC。這僅僅影響日誌文件的轉儲,在 Unix 下以 fsync 轉儲數據。InnoDB 版本從 3.23.40b 開始,在 Unix 下指定 fdatasync 爲使用 fsync 方式、指定 O_DSYNC 爲使用 O_SYNC 方式。由於這在某些 Unix 環境下還有些問題所以在 'data' versions 並沒有被使用。

innodb_force_recovery

警告:此參數只能在你希望從一個被損壞的數據庫中轉儲 (dump)數據的緊急情況下使用! 可能設置的值範圍爲 1 - 6。查看下面的章節 'Forcing recovery' 以瞭解這個參數的具體含義。參數設置大於 0 的值代表着 InnoDB 防止用戶修改數據的安全度。從 3.23.44 開始,這個參數可用。在 my.cnf 中以數字格式設置。

innodb_fast_shutdown

InnoDB 缺少在關閉之前清空插入緩衝。這個操作可能需要幾分鐘,在極端的情況下可以需要幾個小時。如果這個參數據設置爲 1 ,InnoDB 將跳過這個過程而直接關閉。從 3.23.44 和 4.0.1 開始,此參數可用。從 3.23.50 開始,此參數的默認值爲 1。

innodb_thread_concurrency

InnoDB 會試圖將 InnoDB 服務的使用的操作系統進程小於或等於這裏所設定的數值。此參數默認值爲 8。如果計算機系統性能較低或 innodb_monitor 顯示有很多線程等侍信號,應該將這個值設小一點。如果你的計算機系統有很我的處理器與磁盤系統,則可以將這個值設高一點以充分利用你的系統資源。建議設值 爲處理器數目+ 磁盤數目。 從 3.23.44 和 4.0.1 開始,此參數可用。在 my.cnf 中以數字格式設置。

 

而接下來介紹一下新的出場嘉賓 “NDB ”,之所以要介紹這個生力軍的原因有兩個:第一個,對於目前信息爆炸的時代,Mysql 最重要的集羣領域是由他來開拓的,而目前他也不孚衆望,獲得了大家越來越多的關注。第二個,他功能不弱於 Innodb,以目前的情況看起來他極有可能是 Innodb 的未來接班人 (雖然性能方面還有待改進) ~

 

好了,廢話不多說,讓我們來看看石頭在本機上對 NDB 的一些研究成果:

 

1、架設環境:

 

類似於 Oracle 的集羣,NDB Cluster 也包含 “節點” 的概念:數據節點(ndbd),管理節點(mgmd),服務節點(mysqld);他們的啓動順序是:mgmd ---> ndbd ---> mysqld。由於客觀原因,石頭只能先在本機上建立這個模擬的集羣環境,但是多機的配置基本也是一樣的,具體的步驟如下:

 

首先我們下載最新的:mysql-cluster-gpl-7.1.3-linux-x86_64-glibc23.tar.gz ,解壓後安裝到 /usr/local/mysql 下,按照 INSTALL-BINARY 中正常的步驟安裝,此時應該已近建立 (mysql:mysql) 用戶與組,下面會用到。然後嘗試使用 support-files/mysql.server start 進行啓動,若成功則此步驟完成~

 

然後,建立管理節點配置文件 etc/mgmd.cnf:

 

 

接着你可以嘗試啓動管理節點:bin/ndb_mgmd -f etc/mgmd.cnf,然後可以使用命令:bin/ndb_mgm 127.0.0.1 2203 登錄管理節點進行查看,可以看到每個節點的狀態 (可使用 ndb_mgm> show 命令查看),當然現在應該都是 “not connected” 狀態。

 

接下來建立數據節點 etc/ndbd1.cnf (另外一個節點 etc/ndbd2.cnf 類似):

 

 

啓動可以使用命令:bin/ndbd --defaults-file=ndbd1.cnf --initial (注意第一次需要加上 --initial 參數 ),然後另外一個節點也類似的啓動起來,到這裏如果你刷新 mgmd 的狀態,你可以看到兩個節點已經連接上了,並可以顯示出他們的狀態。

 

大家可以注意到,datadir 可能還沒有建立,除了默認的 data/ 目錄,我們還建立 datamgmd/ 和 datandbd/1、datandbd/2 目錄來存儲以上節點的 runtime 文件和 log,這裏別忘記了使:

# chown -R mysql:mysql datamgmd/ datandbd/

# chmod -R +w datamgmd/ datandbd/

來給他們附權哦~

 

最後就是配置具體的 mysql 服務節點了,修改 etc/my.cnf (加入 ndb cluster 配置):

 

 

重啓 mysql.server restart 之後可以看到管理節點中的所有節點都可以看到狀態了,登錄到 mysql 服務器上,使用:show variables like 'have%'; 命令查看 mysql 參數如下:

+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| have_community_features | YES      |
| have_compress           | YES      |
| have_crypt              | YES      |
| have_csv                | YES      |
| have_dynamic_loading    | YES      |
| have_geometry           | YES      |
| have_innodb             | YES      |
| have_ndbcluster         | YES      |
| have_openssl            | DISABLED |
| have_partitioning       | YES      |
| have_query_cache        | YES      |
| have_rtree_keys         | YES      |
| have_ssl                | DISABLED |
| have_symlink            | YES      |
+-------------------------+----------+

 

這就說明安裝成功了,接下來你就可以開始正式的 Mysql 集羣管理之旅了~

 

2、功能對比:

 

基於目前對 NDB 和 Innodb 的測試看來,NDB 和 Innodb 的使用基本是一樣的,ACID (原子性、一致性、隔離性、持久性)實現方式也基本相同,這裏簡單提一下 Mysql 中的幾個隔離級別:

 

 

具體的使用可以參考:http://hideto.javaeye.com/blog/195275 ,總結的相當不錯~

 

但是他們之間有一個很重要的區別:在同一個 transaction 中,如果某一部的執行出錯,Innodb 會繼續的往下執行,而 NDB 則會馬上回滾到最初狀態(類似於 SqlServer 中的 SET XACT_ABORT ON 的狀態),如果不注意這一點的話,在一些極端情況下,系統將出現數據不一致的情況,所以還是需要大家多多注意哦!

 

測試用例如下(在 test 庫中進行測試):

 

[Innodb 用例]

mysql> create table test_innodb (i int not null primary key) engine innodb;

mysql> begin;

mysql> insert into test_innodb values(1);

mysql> insert into test_innodb values(1); # 主鍵重複出錯

mysql> commit;

mysql> select * from test_innodb;

+---+
| i |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

 

[NDB 用例]

mysql> create table test_ndb (i int not null primary key) engine ndbcluster;

mysql> begin;

mysql> insert into test_ndb values(1);

mysql> insert into test_ndb values(1); # 主鍵重複出錯

mysql> commit;

mysql> select * from test_ndb;

Empty set (0.00 sec)

 

累啊,寫了這麼多~ 今天就到這裏吧~ 後面有時間在添加內容~

To be continued ...

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章