淺談 MySQL

一個規模稍大的公司,往往會使用多種數據庫,比如我們公司,就使用了 Oracle, MySQL, 和 Sybase。所以作爲一個系統管理人員,有必要掌握多種數據庫技術。這次,我們來簡單說說 Mysql 的安裝,管理工具,性能監控和提升方法和工具。
 
一. 自動安裝MySQL
相對於其它 ./ocnfigure && make && make install 就可以搞定的軟件來說,MySQL 的安裝步驟較多,也叫麻煩,如果把某些安全加固措施也包括進來的話,步驟就更多了。鑑於此,筆者將安裝的過程寫成了下面的腳本,自動完成安裝過程。附件 mysql 安裝腳本本來是 tgz 文件,因爲不允許上傳 tgz 文件,所以改成了 doc 文件,下載後把擴展名改回 tgz 就可以解壓了。
 
#!/bin/bash
# file name: install_mysql.sh
# function: install a secure mysql server automatically or manully.
# installation regulation: 1) mysql home directory: /usr/local/mysql-5.0.27
#                          2) directories data and log are created to optimize mysql directory structure.
#                          3) rename mysql user "root" to your prefered one and set password for it
#                          4) install customerized my.cnf to /etc/my.cnf
#                          5) install auto-start script to /etc/init.d/mysql
# usage: this script supports two installation mode:
#         1) auto-installation:  you need input nothing.and the result is default setting, that is,
#                                the username of mysql DBA is "mysql_admin" and its password is
#                               "passwd4mysql_admin".
#         2) manual-installation: during the installation process, you will be prompted to make sure
#                                 every step is ok and input username of mysql DBA and its password.
#        how to select installation mode? locate the comment: "# select install mode" and that is. 
# Note: the auto-installation mode is the prefered one. but if you failed to install mysql
# using auto mode, then try manual mode
 
# init var
MYSQL_HOME="/usr/local/mysql-5.0.27"
CURRENT_DIR=`pwd`
 
# select install mode
echo -n "Do you want to install mysql automatically? Y/y to yes:"
read auto_install
 
# add user mysql used to start mysql
if [ `id mysql > /dev/null; echo $?` -eq 1 ] ; then
 useradd -M mysql
fi
 
# install
tar -zxvf mysql-5.0.27.tar.gz > /dev/null
cd mysql-5.0.27
MYSQL_SOURCE_DIR=`pwd`   # save current dir,later will be used
./configure \
--prefix=$MYSQL_HOME \
--sysconfdir=/etc \
--localstatedir=$MYSQL_HOME/data \
--enable-largefile \
--with-big-tables \
--with-charset=gb2312 \
--with-extra-charsets=gbk,utf8 \
--with-mysqld-user=mysql \
--without-debug \
--without-innodb 2>1 1>/dev/null
make 2>1 1>/dev/null
make install 2>1 1>/dev/null
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo  "If installation is OK, then press any key to continue......"
 read install_finished_key
fi
install $CURRENT_DIR/my.cnf /etc/my.cnf
mkdir $MYSQL_HOME/log $MYSQL_HOME/data
touch $MYSQL_HOME/log/mysql-bin.index
$MYSQL_HOME/bin/mysql_install_db 2>1 1>/dev/null
chown -R mysql:root  $MYSQL_HOME
chown -R mysql:mysql $MYSQL_HOME/data
$MYSQL_HOME/bin/mysqld_safe &
sleep 5
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo "If startup is OK, then press any key to continue......"
 read startup_finished_key
fi
 
# safety strengthening
$MYSQL_HOME/bin/mysql -u root -e 'drop database test;delete from mysql.db'
$MYSQL_HOME/bin/mysql -u root -e "delete from mysql.user where not (host='localhost' and user='root');flush privileges"
echo
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo -n "Enter user for MySQL DBA:"
 read USER
 if [ "A$USER" == "A" ] ; then
  USER="mysql_admin"
 fi
else
 USER="mysql_admin"
fi
$MYSQL_HOME/bin/mysql -u root -e "update mysql.user set user='$USER' where user='root';flush privileges"
echo
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo -n "Enter password for user $USER:"
 read PASSWORD
 if [ "A$PASSWORD" == "A" ] ; then
  PASSWORD="passwd4mysql_admin"
 fi
else
 PASSWORD="passwd4mysql_admin"
fi
$MYSQL_HOME/bin/mysqladmin -u $USER password $PASSWORD
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo "Write down your username and password for mysql DBA please,"
 echo "And after you finished, press y/Y to continue......"
 while [ : ] ; do
     read have_written_key
     if [ "A$have_written_key" == "Ay" -o "A$have_written_key" == "AY" ] ; then
          break
     else
          echo "Press y/Y to continue......"
     fi
 done
fi
echo -----------------------------------------------------------------------
$MYSQL_HOME/bin/mysql --user=$USER --password=$PASSWORD -e 'show databases;'
echo -----------------------------------------------------------------------
echo
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo "If strengthen is OK, then press any key to continue......"
 read strengthen_finished_key
fi
 
# configure auto-startup
cp $MYSQL_SOURCE_DIR/support-files/mysql.server /etc/init.d/mysql
chmod 700 /etc/init.d/mysql
chkconfig mysql on
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo "If autostart setting is OK, then press any key to continue......"
 read autostart_finished_key
fi
 
# delete install record file if necessary
if [ "A$auto_install" != "AY" -a "A$auto_install" != "Ay" ] ; then
 echo "Do you wanna delete mysql_history? answer 'Y/y' to delete."
 read if_delete_key
 if [ "A$if_delete_key" == "AY" -o "A$if_delete_key" == "Ay" ] ; then
  rm -f ~/.mysql_history
 fi
fi
exit 0
 
安裝前將下面幾個文件放到一個目錄下:
[root@t12 src]# ll | awk '{ print $9 }'
install_mysql.sh
my.cnf
mysql-5.0.27.tar.gz
然後開始安裝:
[root@t12 src]# sh install_mysql.sh
當安裝腳本提示你
Do you want to install mysql automatically? Y/y to yes:
時,輸入Y/y並回車就OK了。
 
二. Navicat 簡介
MySQL 圖形化管理工具比較多,比如 phpMyAdmin, SQLyog, Navicat 等等。筆者比較常用的是Navicat。Navicat 功能強大,既可以作爲MySQL開發工具,又可以作爲MySQL 管理工具。就開發工具而已,你可以用它來建立各種數據庫對象,比如table,index,procedure,function 等等,方便地設計和生成報表;而作爲管理工具,你可以用它來管理用戶,權限,查看系統運行狀況,導入導出數據,備份和恢復,整理修復數據表,配置任務計劃來執行批作業,執行大多數管理命令(在查詢窗口裏面執行,這也是筆者常用的管理方法)等等。Navicat 的操作也很簡潔明瞭。下面給出用Navicat連接MySQL的窗口和它的主界面,讀者可以從中領略到其簡潔的操作界面和強大的功能。
 
相信對於有一定數據庫圖形管理工具使用經驗的讀者來說,用Navicat來執行MySQL管理和開發任務,都不是什麼困難的事情。
然而,對於用慣了開源工具的我們來說,當碰上了好用的商業軟件時的那種既愛又恨的感覺,相信不少人都有過。Navicat 就是一款商業軟件。不過值得慶幸的是,有破解版,附件中就有一個Navicat2004破解版(我不知道我這樣做會不會“下地獄”,^_^)
就像不能完全依靠圖型界面來管理Oracle一樣,我們也不能把所有的賭注都押在MySQL圖形管理工具上。畢竟,就算圖形管理工具再好用,也有指望不上他們,只好赤手空拳敲命令的時候。所以說,我們還是應該掌握基本的MySQL操作命令。下面說說一些常用的MySQL命令:
1. 連接到本機數據庫:mysql -u <username> -p
2. 在MySQL客戶端查看各種信息:
    help/?: 顯示幫助信息,個人認爲MySQL的幫助系統設計得不錯。
    show variables [ like 'pattern' ];  顯示MySQL系統變量值。
    show status; 顯示服務器狀態信息。
    show create {database | table | procedure | function}; 顯示創建相關數據庫對象是用的語句。
    show binary logs; 顯示二進制日誌文件。
    show {databases | tables }; 顯示所有的數據庫或某個數據庫的所有數據表。
3. 常用的簡單操作命令:
    use <db name>; 選擇當前數據庫。
    create user <username> identified by '<password>'; 創建用戶。
    grant <privileges> on [*|<db name>].* to <username>; 授權給用戶(建議用GUI來作)。
    create database <db name>; 創建數據庫。
上面只列出了筆者常用的命令,更多的命令筆者也記不住,請參考MySQL文檔。
 
三. 性能監控和優化
對於各種不同的數據庫來說,不管是數據庫性能監控方式還是數據庫性能優化方式,在原理和試圖達到的目的上都是大同小異,存在很多的共性。當然,具體的監控和調整方法,過程及相關工具會因爲不同的數據庫而差別很大。比如Oracle性能優化,可以從三個方面入手:硬件升級,內存調優,應用調優。MySQL與之類似,也可以從三個方面下手:硬件升級,進程和內存調優,SQL優化(也就是應用優化)。下面詳述。
(一)MySQL性能監控
首先,我們要清楚,哪些指標可以反映出數據庫的性能。
就MySQL而言,這些指標可以用來測量數據庫性能:
1)CPU,內存和IO在操作系統層面的使用情況;
2)查詢響應時間;
3)吞吐量;
4)各種 Cache 命中率;
 
其次,我們要知道,哪些手段可以用來獲得這些指標。
1)配置 sysstat 來收集數據庫服務器操作系統層面的CPU,內存,IO 等指標;
2)啓用 MySQL 慢查詢記錄功能來記錄下響應時間較長的查詢,這些查詢往往就是需要做MySQL調整的對象。一旦啓用了慢查詢記錄功能後,超過你設置的查詢響應時間的查詢就會被記錄在你指定的日誌文件中,然後,你就可以用mysqldumpslow命令來查看慢查詢了。這樣啓用MySQL慢查詢記錄功能:
# cat /etc/my.cnf
[mysqld]

; enable the slow query log, default 10 seconds

log-slow-queries

; log queries taking longer than 5 seconds

long_query_time = 5

; log queries that don't use indexes even if they take less than long_query_time

; MySQL 4.1 and newer only

log-queries-not-using-indexes
; long query log file
log-slow-queries = /path/to/file
 
這樣查看慢查詢:
# mysqldumpslow /path/to/file
3)收集各種吞吐量和緩存相關信息
      a. 查詢Cache:執行SQL語句 show status like 'qcache%' 收集指標值。
      b. 表緩存:MySQL 表對應於磁盤上的文件,表緩存就是文件緩存。執行SQL語句 show status like 'open%tables' 來收集指標值。
      c. 線程緩存:啓用了線程緩存後,一個線程在其生命週期中就可以服務多個連接,從而加速MySQL初始連接速度。執行SQL語句 show status like 'threads%' 來收集相關指標值。
      d. 關鍵字段(key)緩存:跟緩存表一樣,緩存關鍵字段同樣可以提高查詢效率。執行SQL語句 show status like '%key_read%' 來收集相關指標值。
     e. 臨時表:這裏的臨時表,指的是MySQL內部臨時存放需要進一步處理的數據所使用的表,不是我們在存儲過程中自定義的臨時表。如果臨時表放不下需要臨時存放的數據,MySQL會使用磁盤來存放,從而降低性能。執行SQL語句 show status like 'created_tmp%' 來收集相關指標值。
     f. 排序區: 當MySQL要執行排序操作的時候,它會使用排序區,如果指定的內存排序區放不下需要排序的數據,MySQL會使用磁盤來存放,從而降低性能。執行SQL語句 show status like 'sort%' 來收集相關指標值。
     g. 全表掃描情況:通常情況下,對大表執行全表掃描很低效,應該儘量避免。執行SQL語句 show status like 'com_select%' 和 show status like handler_read_rnd_next%' 來收集相關指標值。
 
再次,我們要知道,這些指標的基準值(也即是在數據庫正常情況下的值)。
爲了判讀我們的數據庫運行狀況是否正常,等待用戶反映異常情況是一種方法,通常情況下這種方法不是我們所希望的,因爲等待用戶反映數據庫異常的時候,往往問題都已經很嚴重了,這時候我們所能做的就是所謂的“應急反應”。更好的更有效的方式是,記錄下正常情況下的基準值,然後實時將當前值跟基準值做對比,一旦當前值開始偏移基準值,就應該預警,這樣,我們就可以做到所謂的“前饋控制”,在問題剛出現時就解決了。
我們應該收集數據庫在各個具有代表性的時間段的基準值,在各種具有代表性的負載時的基準值,尤其是在峯值期間的基準值。收集基準值的方法就是前面講述的用來獲得性能指標值的方法。
對於MySQL性能監控,有幾個工具值得一提,mytop, mysqlard 和 mysqlreport,這些工具的安裝和使用都很簡單,但卻是很有用,讀者可以試試。
 
最後,我們要明白,這些指標異常時,我們應該採取什麼樣的手段,使其恢復到正常的能夠接受的值。這是下面MySQL優化的內容。
(二)MySQL 性能優化
正如前面所說的那樣,MySQL的優化涉及到三個方面:
1)硬件升級:這種方法很簡單,系統負載過高了,好啊,加多CPU;內存不夠用了,沒問題,再加2G內存,等等。“那如果磁盤IO慢了怎麼辦呢?”讀者可能會問。通常情況下,我們不太可能提高磁盤IO的速度(儘管使用合理的RAID級別,比如1+0,可以在一定程度上提高IO性能,但這往往是一錘子的買賣,試想如果數據庫都已經投產了,誰還會輕易去重做RAID。)。實際上磁盤IO跟不上,往往並不是由於磁盤本身IO速度低,而是我們的數據庫過度讀寫磁盤造成的。也就是說,本來可以不用讀磁盤就可以搞定的操作,由於我們沒有配置好,導致數據庫也要去讀磁盤。這種方式往往是一種權宜之計,只能解決燃眉之急。隨着業務量的繼續上升,對數據庫處理能力的要求越來越高,升級後硬件的處理能力很快就不能滿足要求了。因爲數據庫的性能問題,往往是由於數據庫缺乏可伸縮性引起的。所以,解決數據庫性能問題的上策,是提高數據庫的可伸縮性。而這種方法,出發點不是解決可伸縮性問題,當然其作用就有限了。而下面的兩種方法,是以提高數據庫的可伸縮性作爲出發點的。
2)優化MySQL進程和內存:
     a. 啓用查詢緩存: 通過在/etc/my.cnf 文件添加 query_cache_size = < 期望緩存的查詢數 > 來啓用;
     b. 調整表緩存:通過在/etc/my.cnf文件裏面加入 table_cache = <期望緩存的表的數量> 來調整;
     c. 調整MySQL線程緩存:通過在 /etc/my.cnf 文件添加 thread_cache = <期望緩存的進程數> 來調整;
     d. 調整關鍵字段(key)緩存:通過在/etc/my.cnf文件添加 key_buffer = <期望的關鍵字段緩存大小>來調整;
     e. 使用臨時表:通過在/etc/my.cnf文件添加 tmp_table_size max_heap_table_size 來調整;
     f. 設置合適的排序區大小:通過在/etc/my.cnf文件添加 sort_buffer_size = <期望的排序區大小>來調整;
     g. 設置合適的read_buffer_size減少全表掃描次數:通過在/etc/my.cnf文件添加read_buffer_size= <期望的讀緩衝區大小>來調整;
     h. 在大表上建索引:
3)優化SQL語句:那些需要調整的SQL語句,往往都被記錄在了慢查詢日誌文件裏面了,所以,MySQL會告訴我們該優化哪些SQL語句。接下來就是如何優化的問題。讀者可以試試,在一個數百萬行的表上執行"select * from <table_name>會產生什麼效果。不用說,數據庫IO馬上就被堵死了。可是,事實上,剛入行的程序員,就有可能寫出這樣的驚世赫俗的語句來。所以說,作爲系統管理員/DBA,有時間的時候多跟程序員聊聊,提醒他們儘量不要犯這樣的或其它類似的低級錯誤,於人於己都好處多多。關於怎樣才能寫出高效的SQL語句,不敢亂說,一則是因爲我不是SQL高手,二則MySQL 和Oracle文檔有很好的闡述,我不敢班門弄斧。值得指出的是,執行計劃在優化SQL語句的過程中起着十分重要的作用。另外要說明的是,優化SQL語句對於提高數據庫的性能往往是最有效的途徑。
 
閒話:有很多工具可以用來備份MySQL數據庫,不過最有效的最划算的,還是配置MASTER/SLAVE 數據庫。這樣既起到了實時備份的作用,也可以實現一定程度上的負載分擔,提升性能,一箭雙鵰,何樂而不爲。
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章