標簽:mysql
WordPress技巧WordPress優化:為anylink插件增加緩存
先森最近在梳理網站的代碼,想辦法為網站加速,主要從代碼、軟件、網絡層面進行優化,這一切都是從網站切換到HTTPS開始的。先森已經連續觀察了多日的CDN了,目前也就到了查缺補漏的階段了。先森還將整個網站目前備份到了另一臺服務器,將網站在本地解析到這臺服務器上,開始了對代碼的檢查。開啟了debug,把大的一些問題都處理了,然后也把主題的代碼理了一遍,并且網站也加上了Redis緩存。但是先森發現,即使加上了Redis,有時候網頁打開生成時間還是得一秒多,先森就很納悶,一直想搞明白到底是什么情況。排查工具很早以前,先森就在主題的footer.php末尾,添加了下面的代碼,以便于登錄之后可以看到當前網頁的查詢次數,生成時間:<?php if (is_user_logged_in()){ echo "<pre>".get_num_queries().'次查詢,用時'; timer_stop(3); echo '秒</pre>';?>這個代碼網絡上到處都是,相信很多人都添加的有。先森網站加Redis之前,網頁的查詢次數都是150+次,生成時間2-3秒,甚至更多。用上之后減少到50+次,但是有時還是會需要1秒多,讓先森百思不得其解。然后先森把主題代碼該優化的都優化后,查詢次數30+次,生成時間降到1秒左右,但是先森還是不太滿足,所以想看看到底是執行了哪些查詢,然后就在網上找到了這段代碼,和上面的有些類似。首先需要先在WordPress的根目錄配置文件wp-config.php中添加保存查詢的代碼:define('SAVEQUERIES', true);然后也是在footer.php的網頁最后部分添加打印代碼:<?phpif (current_user_can('administrator')){ global $wpdb; echo "<pre>"; print_r($wpdb->queries); echo "</pre>";}?>但是先森添加后看了一下,差點當場去世,這樣打印出來的是一個很大的多維數組,看的人眼花繚亂,重點是太長了還顯示不全。先森將打印復制出來,拿到NotePad++里面打開,依舊顯得很亂。查詢的打印不過大概看了一下,大數組的每一個鍵值表示一個查詢,然后一個查詢數組了,第一個值是執行的SQL,第二個值是使用的時間,第三個值是調用的代碼位置。其實可以用循環做一個網格,讓前端顯示看著方便一點,但是先森很懶,網上看了一下,有插件可以做到相關功能,且不用修改wp-config.php,即Debug Queries,所以先森就懶得自己寫了,直接裝了一個來進行排查。需要注意的是,Debug Queries很久沒有更新了,安裝可能會報錯,不過還是可以正常使用的。其實Debug Queries介紹頁也推薦使用Debug Objects插件,但是先森試了一下Debug Queries可以用,也就懶得再試另一個插件了。排查問題工具準備好了,先森就來好好排查到底是哪里查詢比較慢了。插件裝好了,再去看打印出來的查詢信息,就比較清晰了。先森對比了一下,大部分的查詢都是0.00x秒的,就是幾毫秒的,但是只要涉及到wp_al_urls的查詢,就會是即時甚至上百毫秒。wp_al_urls的查詢先森看了一下,這個表是插件anylink的,這個插件主要是將網站上的外鏈全都轉化成內鏈,點擊后可以跳轉到外鏈。對于anylink,先森這里也發過兩篇相關的文章:WordPress為anylink插件外鏈跳轉添加漂亮的跳轉頁面WordPress:WPJAM BASIC插件與anylink沖突這個插件先森也是從建站伊始就在用了,是一個很好用的插件,但沒有想到這個插件會出現慢查詢。通過上面的截圖可以看到,對wp_al_urls的查詢條件是網站鏈接,看了一下數據庫,這個SQL是為了去拿到內鏈的slug記錄:anylink獲取slug這里去查的,實際上是網頁正文里的外鏈、各位評論大佬的網址對應的內鏈地址。先森看了一下這個表,沒想到竟然有10M的大小,接近10萬條數據,而且這里查詢的是al_origURL字段,先森看了一下,這個字段是沒有索引的。解決問題對于MySQL的查詢,先森能想到的優化方法就是加索引,所以先森直接就操作加索引,但是報錯了:給al_origURL字段加索引報錯看報錯是跟字段格式有關的,看了一下這個字段的類型是mediumtext的,這個字段是存URL的,有些URL非常的長,如果該varchar的話,可能會出問題,varchar最長255個字符。網上找了一陣子解決方案,都是說text相關的類型無法加索引。先森本來就對數據庫索引什么的不太了解,所以只能放棄這條路。先森還能想到的辦法,就是看下這個查詢的代碼,想辦法把結果存到Redis上緩存起來。至于怎么找到實際執行的代碼,先森看了一下,直接找調用的最后一段就可以了。找到慢查詢的調用代碼可以看到,兩個SQL實際上是一樣的,查的是同個網址,結果執行的時間竟然都比較長,所以確實得把結果緩存起來。為了優化代碼,先森把整個網站都作為了一個PhpStorm里的一個項目,不得不說一個好的IDE工具寫起代碼來是真的舒服。直接全局搜索,尋找get_slug_by_url這個函數,順利找到了代碼所在。搜索get_slug_by_url函數這里有兩個結果,第一個是原本的函數,已經被先森注釋起來了,第二個是先森改了之后的。可以看到這個函數就是調用$wpdb來執行SQL語句,將得到的結果再返回一下。函數比較簡單,也很利于先森修改。然后先森又找了一下WordPress如何添加緩存,結果找到一下,發現非常簡單。WordPress操作緩存WordPress 為我們提供了使用對象緩存的函數,方便我們使用對象緩存。wp_cache_add() :添加數據到緩存中,如果數據已存在,返回 flasewp_cache_set() :添加數據到緩存中,如果數據已存在,會覆蓋數據wp_cache_get() :獲取緩存中的數據,如果數據不存在,返回 falsewp_cache_delete() : 從緩存中刪除數據wp_cache_replace() :替換緩存中的數據,類似 wp_cache_set,但是如果數據不存在,不自動添加wp_cache_flush():清除所有緩存如果沒有裝redis緩存插件,上面的這些函數是在./wp-includes/cache.php里。如果裝了Redis Object Cache等插件,就會自動增加一個./wp-content/object-cache.php文件,這些函數也會存在于這個文件中,用于存入緩存。WordPress 對象緩存使用使用示例$result = wp_cache_get( 'my_result' );if ( false === $result ) { $result = $wpdb->get_results( $query ); wp_cache_set( 'my_result', $result );}對anylink的get_slug_by_url函數改造有了上面這個案例,先森為anylink的函數增加緩存就很方便了。示例很簡單,get_slug_by_url函數本身也簡單,所以改造后如下:public function get_slug_by_url( $url ) { $arr_slug = wp_cache_get( $url ); if ( false === $arr_slug ) { global $wpdb; $arr_slug = array(); $arr_slug = $wpdb->get_row($wpdb->prepare( "SELECT * FROM " . ANYLNK_DBTB . " WHERE al_origURL = %s", $url ), ARRAY_A); wp_cache_set( $url, $arr_slug ); } return $arr_slug;}因為示例和函數太契合了,所以這個函數幾乎就和示例結構一樣。首先去Redis獲取緩存數據,獲取不到就去MySQL查詢,查到后再存到Redis。2022年4月4日更新:此代碼存在億點點bug,修復參考此文章:修復anylink增加Redis緩存后存在的bug檢查效果代碼修改后,同步到測試服務器,訪問了兩次之前訪問的頁面,查詢次數和用時都降下來了。然后看到查詢次數還是有33次,其中有部分是查詢wp_al_urls_index這個表的,雖然速度不慢,但是次數比較多,先森重復上面的方法也修改了一下相關函數,最終效果如下圖:最終效果查看Redis的keys上面改造的代碼中,是拿url地址去做的key名稱,那么先森也來看下緩存數據在Redis里的情況:redis的緩存上面改造的代碼比較簡陋,直接拿的URL做的key名稱,如果URL比較短還好,如果長的話就可能出現問題,key名稱其實可以做一下長度限制。提示:Redis最好不要使用默認端口6379,除非安全做的非常好。使用Redis時注意以下幾點:1、一定要配置強密碼;2、安全組、防火墻一定要最小范圍放通Redis端口,即針對指定IP放通訪問;3、盡量不要使用默認端口。因為Redis而導致服務器中木馬病毒的保障,先森這邊經常遇到。總結先森以前以為給WordPress配上Redis很麻煩,實際使用發現真香,建議有能力的朋友都上一下,畢竟生命不止,折騰不息。本文最主要的還是記錄一下排查網頁查詢慢的過程和解決方法,希望能夠給其他朋友提供思路。
系統運維, 經驗雜筆查看、刪除MySQL匿名用戶
一個網站,甚至一個業務,數據庫都是防護的重中之重,如果MySQL存在匿名用戶,那么危險可想而知。先森在這里做個記錄,查找和刪除匿名用戶的SQL,其實變換一下也可以查無密碼用戶。查看匿名用戶SQL很簡單,最簡單的查:mysql> select host,user from mysql.user where user='';通常mysql會默認有兩個匿名用戶,如果在安裝MySQL的時候沒有特殊措施,那么一般都存在如下結果:匿名用戶刪除匿名用戶刪除的SQL也很簡單,只是沒有查詢那么常用:mysql> delete from mysql.user where user='';

川公網安備 51011202000104號