如何在Linux指令行下快速監控mysql?
其實很簡單,就是利用linux下的watch 工具來做監控,方法如下:
[yejr@localhost imysql]# watch -d -n 10 "egrep 'MySQL thread|Log|Modified db pages' innodb_status.3249 "
Every 10.0s: egrep 'MySQL thread|Log|Modified db pages' innodb_status.3249 Thu Apr 9 10:01:12 2009
MySQL thread id 6, query id 71 localhost root Sending data
Log sequence number 2703 3443241402
Log flushed up to 2703 3442763607
Modified db pages 83325
或者:
[yejr@localhost imysql]#watch -d -n 10 "mysqladmin ext|egrep Innodb_data"
Every 10.0s: mysqladmin ext|egrep Innodb_data Thu Apr 9 10:03:55 2009
| Innodb_data_fsyncs | 4144699 |
| Innodb_data_pending_fsyncs | 0 |
| Innodb_data_pending_reads | 0 |
| Innodb_data_pending_writes | 0 |
| Innodb_data_read | 5567172608 |
| Innodb_data_reads | 298413 |
| Innodb_data_writes | 4492881 |
| Innodb_data_written | 18549422080 |
參數解釋:
-d --differences
-n --interval
如何更改MySQL的預設字元集?
方法1、 用 SET 文法來指定,不加 "GLOBAL" 的話就隻對本次會話有效
SET [GLOBAL] character_set_client = utf8;
SET [GLOBAL] character_set_connection = utf8;
SET [GLOBAL] character_set_database = utf8;
SET [GLOBAL] character_set_results = utf8;
SET [GLOBAL] character_set_server = utf8;
方法2、 也用SET文法,隻對本次會話有效
SET NAMES 'utf8';
方法3、) 直接修改 my.cnf,增加一行内容,然後重新開機 MySQL,使之全局生效
default-character-set = utf8
如何快速對調字段裡面的某些列?
問題:表 t 有個字段叫做 c,現在想要把 c 裡面的第 10 和 第 11 列位置對調一下,咋辦啊?
答案:用下面的辦法吧,不過本例隻對ascii字元有作用,中文或其他的就另外想辦法。
mysql>set @pos1 = 10;
mysql>set @pos2 = 11;
mysql>UPDATE t SET c = CONCAT(
LEFT(c,@pos1-1), -- 第 10 列以前的值
SUBSTR(c,@pos2,1), -- 第 11 列的值
SUBSTR(c,@pos1+1,@pos2-@pos1-1), -- 第 10 到第 11 列之間的值
SUBSTR(c,@pos1,1), -- 第 10 列
RIGHT(c, LENGTH(c) - @pos2)); -- 第 11 列之後的值
為何會出現大量unauthenticated user?
看下手冊中的解釋是:unauthenticated user refers to a thread that has become associated with a client connection but for which authentication of the client user has not yet been done。意即:有一個線程在處理用戶端的連接配接,但是該用戶端還沒通過使用者驗證。
原因可能有:
1 伺服器在做DNS反響解析,解決辦法有2:
1)在 hosts 中添加用戶端ip,如
192.168.0.1 yejr
2)MySQL啟動參數增加一個skip-name-resolve,即不啟用DNS反響解析
2、伺服器的線程還處于排隊狀态,是以可以加大 back_log
資料不算大,備份卻非常慢?
環境
硬體:DELL 1950, 146G SAS 15K RPMS * 2, 8G Ram
軟體:2.6.9-55.ELsmp x86_64, mysql 5.1.x
現象
2個庫,其中1個業務庫下有20多個表,表檔案大小總量不到2G。
另一個為日志庫,下400多個表,大緻是每天會産生5個表,其中有一個表較大,約400MB,總量約40多GB。
每次備份耗時較長,最嚴重的一次花了5個多小時才完成。
業務庫為目前活動庫,日志庫則主要用作備份,每天日志歸檔,過期資料表很少有讀寫請求。
InnoDB Buffer Pool總共配置設定了2G,從系統指令 top 結果來看,mysqld 隻配置設定了1.7G 記憶體,buffer pool 并沒有全部耗盡。
SHOW ENGINE INNODB STATUS 結果中也看到了,buffer pool 确實沒用完,還有不少空閑的。
備份時,觀察 vmstat 結果,發現 bi 和 bo 的量較大,而且兩個的值基本相當,備份其中一個表約 500MB,耗時46 秒。
按照這個耗時計算,全部備份出來也不需要5個多小時,這是為什麼呢?
分析
大家先分析下,看是什麼原因,稍後給出答案 :)
原因
其實問題原因很簡單,但一般人不容易想到。那就是,那些曆史的日志表,由于長時間不讀取,大部分資料沒有在innodb buffer中。是以,每次備份時,大部分資料都要産生大量的實體讀,然後再産生實體寫,然而該伺服器隻有2塊硬碟,I/O性能有限,是以備份非常慢。
這時候,我們可以有幾種解決辦法:
1. 删除過期日志表,或者放到線下的歸檔資料庫上
2. 如果innodb buffer還有大量空閑的話,可以不定期執行select * from table,将這部分資料load到buffer中,減少備份時的實體I/O,提高速度
磁盤空間滿了之後MySQL會怎樣?
當磁盤空間爆滿後,MySQL會發生什麼事呢?又應該怎麼應對?
會發生什麼事
當磁盤空間寫滿了之後,MySQL是無法再寫入任何資料的,包括對表資料的寫入,以及binlog、binlog-index等檔案。
當然了,因為InnoDB是可以把髒資料先放在記憶體裡,是以不會立刻表現出來無法寫入,除非開啟了binlog,寫入請求才會被阻塞。
當MySQL檢測到磁盤空間滿了,它會:
每分鐘:檢查空間是否得到釋放,以便寫入新資料。當發現有剩餘空間了,就會繼續寫入資料,一切照舊。
每十分鐘:如果還是發現沒剩餘空間,則會在日志中寫入一條記錄,報告磁盤空間滿(這時候隻寫入幾個位元組還是夠的)。
應該怎麼辦
那麼,當發現磁盤空間滿了之後,我們應該怎麼處理呢,建議:
提高監控系統檢測頻率,預防再次發生;
及時删除不用的檔案,釋放空間;
若有線程因磁盤滿的問題被阻塞了,可先殺掉,等到下一分鐘重新檢測時它可能又可以正常工作了;
可能因磁盤滿導緻某些線程被阻塞,引發其他線程也被阻塞,可把導緻阻塞的線程殺掉,其他被阻塞的線程也就能繼續工作了。
例外
有個例外的情況是:
當執行 REPAIR TABLE 或者OPTIMIZE TABLE 操作時,或者執行完 LOAD DATA INFILE 或 ALTER TABLE 之後批量更新索引時,這些操作會建立臨時檔案,當執行這些操作過程中mysqld發現磁盤空間滿了,就會把這個涉及到的表标記為crashed,删掉臨時檔案(除了 ALTER TABLE 操作,MySQL會放棄正在執行的操作,删除臨時檔案,釋放磁盤空間)。
備注:當執行這些指令過程中mysqld程序被意外被殺掉的話,其所生成臨時檔案不會自動删除,需要手工删掉才能釋放磁盤空間。
以上内容來自于《雲資料庫運維實戰手冊》電子書,可點選
https://developer.aliyun.com/topic/download?id=8198下載下傳完整版,助力雲運維能力更上一層樓!