MySQL 在崩潰恢復時,會遍歷打開所有 ibd 文件的 header page 驗證數據字典的準確性,如果 MySQL 中包含了大量表,這個校驗過程就會比較耗時。 MySQL 下崩潰恢復確實和表數量有關,表總數越大,崩潰恢復時間越長。另外磁盤 IOPS 也會影響崩潰恢復時間,像這里開發(fā)庫的 HDD IOPS 較低,因此面對大量的表空間,校驗速度就非常緩慢。另外一個發(fā)現,MySQL 8 下正常啟用時居然也會進行表空間校驗,而故障恢復時則會額外再進行一次表空間校驗,等于校驗了 2 遍。不過 MySQL 8.0 里多了一個特性,即表數量超過 5W 時,會啟用多線程掃描,加快表空間校驗過程。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名申請、網站空間、營銷軟件、網站建設、咸寧網站維護、網站推廣。
如何跳過校驗MySQL 5.7 下有方法可以跳過崩潰恢復時的表空間校驗過程嘛?查閱了資料,方法主要有兩種:
1. 配置 innodb_force_recovery可以使 srv_force_recovery != 0 ,那么 validate = false,即可以跳過表空間校驗。實際測試的時候設置 innodb_force_recovery =1,也就是強制恢復跳過壞頁,就可以跳過校驗,然后重啟就是正常啟動了。通過這種臨時方式可以避免崩潰恢復后非常耗時的表空間校驗過程,快速啟動 MySQL,個人目前暫時未發(fā)現有什么隱患。2. 使用共享表空間替代獨立表空間這樣就不需要打開 N 個 ibd 文件了,只需要打開一個 ibdata 文件即可,大大節(jié)省了校驗時間。自從聽了姜老師講過使用共享表空間替代獨立表空間解決 drop 大表時性能抖動的原理后,感覺共享表空間在很多業(yè)務環(huán)境下,反而更有優(yōu)勢。
臨時冒出另外一種解決想法,即用 GDB 調試崩潰恢復,通過臨時修改 validate 變量值讓 MySQL 跳過表空間驗證過程,然后讓 MySQL 正常關閉,重新啟動就可以正常啟動了。但是實際測試發(fā)現,如果以 debug 模式運行,確實可以臨時修改 validate 變量,跳過表空間驗證過程,但是 debug 模式下代碼運行效率大打折扣,反而耗時更長。而以非 debug 模式運行,則無法修改 validate 變量,想法破滅。
A、設置索引項,應該是出現在where后面的列,或者連接字句中出現的列;
B、使用唯一索引,索引的基數越大,索引查詢的效果越好,舉例:查詢條件中含有索引字段和非索引字段的時候,會優(yōu)先走索引篩選出數據,然后在數據中回表過濾沒有走索引的字段,但是Mysql任務,如果索引篩選出的數據量大于20%,會認為此時走索引效果不如全表掃描,繼而放棄索引,走全表掃描來查詢;
C、使用短索引,例如一個屬性200多位,其實索引只要創(chuàng)建前幾位效果會好;
D、最左原則,組合索引中,靈活運用最左前綴;
E、不要過度使用索引,索引會占用空間,影響寫入的速度;
我去了相關網站下載,它只有384K字節(jié)大小。它把兩個文件(一個可執(zhí)行文件.exe和一個動態(tài)鏈接庫文件.dll)安裝到C:\PRogram Files\SQLyog路徑下。然后運行可執(zhí)行文件。 安裝后沒有必要再訪問該網站了,我訪問該網站是得到了一個消息,說它的域名沒有設置(configured)、登記、或正在建設中。我不清楚這個問題是暫時的還是一直是這樣。該軟件是免費的,并且沒有標志廣告(banner ads),所以它可能是一個特定的尚未最終定型的商業(yè)模型。最終可能還是要負費的。 數據庫、表格(table)和列樹(column tree)該程序一啟動就開始詢問我的登錄到MySOL服務器的口令。我只需要輸入我的服務器名字、用戶id和登錄密碼。所有其它的設置都是正確的默認值。然后(當我開始其它事務、重啟幾次、睡了一會之后),我重新運行該程序,這時只需要再次輸入我的登錄密碼。該程序沒有保存密碼的選項,你可以認為這是該程序的一個bug,也可以說是程序的保密特性。 一旦你登錄之后,界面就是很值得注意。MySOL服務器上所有的數據庫都顯示在一個樹型控件上。你只能訪問你在登錄時授權的那個數據庫。如果你點開代表授權給你的那個數據庫的樹型結構,你就可以看到一系列代表表格的節(jié)點。點開表格節(jié)點后,你就可以看到一系列顯示字段名的節(jié)點和另一個代表索引的節(jié)點集合。 索引界面絕對是個好東東,這樣你就可以CRUD查詢索引和關鍵字了。這相對前端數據庫如Microsoft access來說是個提高。如果考慮到MySOL剛剛開始提供對主(primary)和非相關(foreign)關鍵字關系的支持,本程序這部分的設計是很成熟的。在右下方的面板上,有四個標簽頁,即:結果(Result)、消息(Message)、對象(Object)和歷史(History)。 有什么缺點?我試圖發(fā)現該程序的缺點,不過只發(fā)現了一個。如果你在Win32 Dependency Walker下運行程序的.exe文件,你會發(fā)現它引用了COMDLG32.dll文件,而COMDLG32.dll又輪流引用AppHelp。實事上,CommDlg調用AppHelp,而當AppHelp沒有請求函數時,CommDlg這么做根本就是浪費資源。 過于簡單?在SQLyog FAQ上,有一種觀點認為該軟件沒有正式歸檔的必要。當然,FAQ(常見問題解答)本身就是一種歸檔。SQLyog的界面非常直觀。我建議你打印一份MySOL文檔(包括SQL特殊語法擴展)。我就是這么做的,它只用了一個半英寸的活頁封面。 最后一步?FAQ還讓人想到一個讓人耳朵起了老繭卻又是正確的Occam's Razor準則——一切超出必要的復雜性都是沒有必要的。我之所以到處“推銷”這個工具,就是因為它可以為我們提供一個可以管理MySOL服務器上許多數據庫的、簡單的、圖形化的界面。它的速度極快,并且它的拷貝很?。梢苑旁谝粡堒洷P上)。 SQLyog宣稱自己是一個查詢分析器,實際上它的功能遠遠不止這些。
錯誤日志和訪問日志一樣也是Apache的標準日志。本文分析錯誤日志的內容,介紹如何設置和錯誤日志相關的選項,文檔錯誤和CGI錯誤的分類,以及如何方便地查看日志內容,等等。
一、位置和內容
錯誤日志無論在格式上還是在內容上都和訪問日志不同。然而,錯誤日志和訪問日志一樣也提供豐富的信息,我們可以利用這些信息分析服務器的運行情況、哪里出現了問題。
錯誤日志的文件名字是error_log,但如果是Windows平臺,則錯誤日志的文件名字是error.log。錯誤日志的位置可以通過ErrorLog指令設置:
ErrorLog logs/error.log
除非文件位置用“/”開頭,否則這個文件位置是相對于ServerRoot目錄的相對路徑。如果Apache采用默認安裝方式安裝,那么錯誤日志的位置應該在/usr/local/apache/logs下。但是,如果Apache用某種包管理器安裝,錯誤日志很可能在其他位置。
正如其名字所示,錯誤日志記錄了服務器運行期間遇到的各種錯誤,以及一些普通的診斷信息,比如服務器何時啟動、何時關閉等。
我們可以設置日志文件記錄信息級別的高低,控制日志文件記錄信息的數量和類型。這是通過LogLevel指令設置的,該指令默認設置的級別是error,即記錄稱得上錯誤的事件。有關該指令中允許設置的各種選項的完整清單,請參見的Apache文檔。
大多數情況下,我們在日志文件中見到的內容分屬兩類:文檔錯誤和CGI錯誤。但是,錯誤日志中偶爾也會出現配置錯誤,另外還有前面提到的服務器啟動和關閉信息。
二、文檔錯誤
文檔錯誤和服務器應答中的400系列代碼相對應,最常見的就是404錯誤——Document Not Found(文檔沒有找到)。除了404錯誤以外,用戶身份驗證錯誤也是一種常見的錯誤。
404錯誤在用戶請求的資源(即URL)不存在時出現,它可能是由于用戶輸入的URL錯誤,或者由于服務器上原來存在的文檔因故被刪除或移動。
順便說一下,按照Jakob Nielson的意見,在不提供重定向或者其他補救措施的情況下,我們永遠不應該移動或者刪除Web網站的任何資源。Nielson的更多文章,請參見。
當用戶不能打開服務器上的文檔時,錯誤日志中出現的記錄如下所示:
[Fri Aug 18 22:36:26 2000] [error]
[client 192.168.1.6] File does not exist:
/usr/local/apache/bugletdocs/Img/south-korea.gif
可以看到,正如訪問日志access_log文件一樣,錯誤日志記錄也分成多個項。
錯誤記錄的開頭是日期/時間標記,注意它們的格式和access_log中日期/時間的格式不同。access_log中的格式被稱為“標準英文格式”,這或許是歷史跟我們開的一個玩笑,但現在要改變它已經太遲了。
錯誤記錄的第二項是當前記錄的級別,它表明了問題的嚴重程度。這個級別信息可能是LogLevel指令的文檔中所列出的任一級別(參見前面LogLevel的鏈接),error級別處于warn級別和crit級別之間。404屬于error錯誤級別,這個級別表示確實遇到了問題,但服務器還可以運行。
錯誤記錄的第三項表示用戶發(fā)出請求時所用的IP地址。
記錄的最后一項才是真正的錯誤信息。對于404錯誤,它還給出了完整路徑指示服務器試圖訪問的文件。當我們料想某個文件應該在目標位置卻出現了404錯誤時,這個信息是非常有用的。此時產生這種錯誤的原因往往是由于服務器配置錯誤、文件實際所處的虛擬主機和我們料想的不同,或者其他一些意料不到的情況。
由于用戶身份驗證問題而出現的錯誤記錄如下所示:
[Tue Apr 11 22:13:21 2000]
[error] [client 192.168.1.3] user rbowen@rcbowen.
com: authentication failure for "/cgi-bin/hirecareers/company.cgi":
password mismatch
注意,由于文檔錯誤是用戶請求的直接結果,因此它們在訪問日志中也會有相應的記錄。
三、CGI錯誤
錯誤日志最主要的用途或許是診斷行為異常的CGI程序。為了進一步分析和處理方便,CGI程序輸出到STDERR(Standard Error,標準錯誤設備)的所有內容都將直接進入錯誤日志。這意味著,任何編寫良好的CGI程序,如果出現了問題,錯誤日志就會告訴我們有關問題的詳細信息。
然而,把CGI程序錯誤輸出到錯誤日志也有它的缺點,錯誤日志中將出現許多沒有標準格式的內容,這使得用錯誤日志自動分析程序從中分析出有用的信息變得相當困難。
下面是一個例子,它是調試Perl CGI代碼時,錯誤日志中出現的一個錯誤記錄:
[Wed Jun 14 16:16:37 2000] [error] [client 192.168.1.3] Premature
end of script headers: /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi
Global symbol "$rv" requires explicit package name at
/usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 81.
Global symbol "%details" requires explicit package name at
/usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 84.
Global symbol "$Config" requires explicit package name at
/usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 133.
Execution of /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi
aborted due to compilation errors.
可以看到,CGI錯誤和前面的404錯誤格式相同,包含日期/時間、錯誤級別以及客戶地址、錯誤信息。但這個CGI錯誤的錯誤信息有好幾行,這往往會干擾一些錯誤日志分析軟件的工作。
有了這個錯誤信息,即使是對Perl不太熟悉的人也能夠找出許多有關錯誤的信息,例如至少可以方便地得知是哪幾行代碼出現了問題。Perl在報告程序錯誤方面的機制是相當完善的。當然,不同的編程語言輸出到錯誤日志的信息會有所不同。
由于CGI程序運行環(huán)境的特殊性,如果沒有錯誤日志的幫助,大多數CGI程序的錯誤都將很難解決。
有不少人在郵件列表或者新聞組中抱怨說自己有一個CGI程序,當打開網頁時服務器卻返回錯誤,比如“Internal Server Error”。我們可以肯定,這些人還沒有看過服務器的錯誤日志,或者根本不知道錯誤日志的存在。決多大多數情況下,錯誤日志能夠精確地指出CGI錯誤的所在以及如何修正這個錯誤。
四、查看日志文件
我常常告訴別人說,在進行開發(fā)的同時我會不斷地檢查服務器的日志,以便能夠立即知道哪兒出了問題。但我得到的回答卻往往是沉默。起先我以為這種沉默意味著“你當然得這樣做”,后來我才發(fā)現這種沉默的真正含義是“我不知道別人的做法,但我自己是不干的。”
雖然如此,下面我們還是要看看如何方便地查看服務器日志文件。用telnet連接到服務器,然后輸入下面的命令:
tail -f /usr/local/apache/logs/error_log
該命令將顯示出日志文件的最后幾行內容,如果有新的內容加入到日志文件,它還會立即顯示出新加入的內容。
Windows用戶也同樣可以使用這種方法,比如可以使用各種為Windows提供的Unix工具軟件包。我個人愛好一個稱為AINTX的工具,它可以在找到。
還有一種替代方法是使用下面的Perl代碼,它利用了一個稱為File::Tail的模塊:
use File::Tail;
$file=File::Tail-new("/some/log/file");
while (defined($line=$file-read)) {
print "$line";
}
無論具體采用的是哪一種方法,同時打開多個終端窗口都是一種好習慣:比如在一個窗口中顯示錯誤日志,在另一個窗口中顯示訪問日志。這樣,我們就能夠隨時獲知網站上發(fā)生的事情并立即予以解決。轉載
MySQL 的 Binlog 記錄著 MySQL 數據庫的所有變更信息,了解 Binlog 的結構可以幫助我們解析Binlog,甚至對 Binlog 進行一些修改,或者說是“篡改”,例如實現類似于 Oracle 的 flashback 的功能,恢復誤刪除的記錄,把 update 的記錄再還原回去等。本文將帶您探討一下這些神奇功能的實現,您會發(fā)現比您想象地要簡單得多。本文指的 Binlog 是 ROW 模式的 Binlog,這也是 MySQL 8 里的默認模式,STATEMENT 模式因為使用中有很多限制,現在用得越來越少了。
Binlog 由事件(event)組成,請注意是事件(event)不是事務(transaction),一個事務可以包含多個事件。事件描述對數據庫的修改內容。
現在我們已經了解了 Binlog 的結構,我們可以試著修改 Binlog 里的數據。例如前面舉例的 Binlog 刪除了一條記錄,我們可以試著把這條記錄恢復,Binlog 里面有個刪除行(DELETE_ROWS_EVENT)的事件,就是這個事件刪除了記錄,這個事件和寫行(WRITE_ROWS_EVENT)的事件的數據結構是完全一樣的,只是刪除行事件的類型是 32,寫行事件的類型是 30,我們把對應的 Binlog 位置的 32 改成 30 即可把已經刪除的記錄再插入回去。從前面的 “show binlog events” 里面可看到這個 DELETE_ROWS_EVENT 是從位置 378 開始的,這里的位置就是 Binlog 文件的實際位置(以字節(jié)為單位)。從事件(event)的結構里面可以看到 type_code 是在 event 的第 5 個字節(jié),我們寫個 Python 小程序把把第383(378+5=383)字節(jié)改成 30 即可。當然您也可以用二進制編輯工具來改。
找出 Binlog 中的大事務
由于 ROW 模式的 Binlog 是每一個變更都記錄一條日志,因此一個簡單的 SQL,在 Binlog 里可能會產生一個巨無霸的事務,例如一個不帶 where 的 update 或 delete 語句,修改了全表里面的所有記錄,每條記錄都在 Binlog 里面記錄一次,結果是一個巨大的事務記錄。這樣的大事務經常是產生麻煩的根源。我的一個客戶有一次向我抱怨,一個 Binlog 前滾,滾了兩天也沒有動靜,我把那個 Binlog 解析了一下,發(fā)現里面有個事務產生了 1.4G 的記錄,修改了 66 萬條記錄!下面是一個簡單的找出 Binlog 中大事務的 Python 小程序,我們知道用 mysqlbinlog 解析的 Binlog,每個事務都是以 BEGIN 開頭,以 COMMIT 結束。我們找出 BENGIN 前面的 “# at” 的位置,檢查 COMMIT 后面的 “# at” 位置,這兩個位置相減即可計算出這個事務的大小,下面是這個 Python 程序的例子。
切割 Binlog 中的大事務
對于大的事務,MySQL 會把它分解成多個事件(注意一個是事務 TRANSACTION,另一個是事件 EVENT),事件的大小由參數 binlog-row-event-max-size 決定,這個參數默認是 8K。因此我們可以把若干個事件切割成一個單獨的略小的事務
ROW 模式下,即使我們只更新了一條記錄的其中某個字段,也會記錄每個字段變更前后的值,這個行為是 binlog_row_image 參數控制的,這個參數有 3 個值,默認為 FULL,也就是記錄列的所有修改,即使字段沒有發(fā)生變更也會記錄。這樣我們就可以實現類似 Oracle 的 flashback 的功能,我個人估計 MySQL 未來的版本從可能會基于 Binlog 推出這樣的功能。
了解了 Binlog 的結構,再加上 Python 這把瑞士軍刀,我們還可以實現很多功能,例如我們可以統計哪個表被修改地最多?我們還可以把 Binlog 切割成一段一段的,然后再重組,可以靈活地進行 MySQL 數據庫的修改和遷移等工作。