進行建立資料庫的連線是非常複雜的。所以在使用的時候儘量減少建立連線的動作。也就是盡量使用長連線。但是當全部使用長連線的時候,有時候你會發現mysql的記憶體增長的非常之快。這是因為mysql在執行的過程中臨時使用的記憶體是管理在連線物件裡面的。這些資源會在斷開連線的時候才會進行釋放。所以如果長連線積累下來的話,可能占用的記憶體太大,被系統強制殺掉。從現象看就是mysql異常重啟了。解決這個問題的話有兩種方案:
定期進行斷開長連線。使用一段時間,或者程式執行乙個占用記憶體很大的查詢之後,斷開連線,之後重新連線在查詢。
如果你用的是 mysql 5.7 或更新版本,可以在每次執行乙個比較大的操作後,通過執 行 mysql_reset_connection 來重新初始化連線資源。這個過程不需要重連和重新做權 限驗證,但是會將連線恢復到剛剛建立完時的狀態。
連線建立完成後,你就可以執行 select 語句了。執行邏輯就會來到第二步:查詢快取。
mysql 拿到乙個查詢請求後,會先到查詢快取看看,之前是不是執行過這條語句。之前 執行過的語句及其結果可能會以 key-value 對的形式,被直接快取在記憶體中。key 是查詢 的語句,value 是查詢的結果。如果你的查詢能夠直接在這個快取中找到 key,那麼這個 value 就會被直接返回給客戶端。如果語句不在查詢快取中,就會繼續後面的執行階段。執行完成後,執行結果會被存入查 詢快取中。你可以看到,如果查詢命中快取,mysql 不需要執行後面的複雜操作,就可 以直接返回結果,這個效率會很高。
在一般情況下 不建議使用查詢快取,因為查詢快取的弊大於利。查詢快取的失效非常頻繁,只要有對乙個表的更新,這個表上所有的查詢快取都會被清 空。因此很可能你費勁地把結果存起來,還沒使用呢,就被乙個更新全清空了。對於更新 壓力大的資料庫來說,查詢快取的命中率會非常低。除非你的業務就是有一張靜態表,很 長時間才會更新一次。比如,乙個系統配置表,那這張表上的查詢才適合使用查詢快取。好在 mysql 也提供了這種「按需使用」的方式。你可以將引數 query_cache_type 設定 成 demand,這樣對於預設的 sql 語句都不使用查詢快取。而對於你確定要使用查詢緩 存的語句,可以用 sql_cache 顯式指定,像下面這個語句一樣:
select sql_cache * from t where id=10
需要注意的是,mysql 8.0 版本直接將查詢快取的整塊功能刪掉了,也就是說 8.0 開始徹 底沒有這個功能了
如果沒有命中查詢快取,就要開始真正執行語句了。首先,mysql 需要知道你要做什 麼,因此需要對 sql 語句做解析。分析器先會做「詞法分析」。你輸入的是由多個字串和空格組成的一條 sql 語句, mysql 需要識別出裡面的字串分別是什麼,代表什麼。做完了這些識別以後,就要做「語法分析」。根據詞法分析的結果,語法分析器會根據語 法規則,判斷你輸入的這個 sql 語句是否滿足 mysql 語法。
經過了分析器,mysql 就知道你要做什麼了。在開始執行之前,還要先經過優化器的處 理。優化器是在表裡面有多個索引的時候,決定使用哪個索引;或者在乙個語句有多表關聯 (join)的時候,決定各個表的連線順序。比如你執行下面這樣的語句,這個語句是執行 兩個表的 join:
select * from t1 join t2 using(id) where t1.c=10 and t2.d=20;
既可以先從表 t1 裡面取出 c=10 的記錄的 id 值,再根據 id 值關聯到表 t2,再判斷 t2 裡面 d 的值是否等於 20。也可以先從表 t2 裡面取出 d=20 的記錄的 id 值,再根據 id 值關聯到 t1,再判斷 t1 裡面 c 的值是否等於 10。這兩種執行方法的邏輯結果是一樣的,但是執行的效率會有不同,而優化器的作用就是決 定選擇使用哪乙個方案。優化器階段完成後,這個語句的執行方案就確定下來了,然後進入執行器階段。
mysql 通過分析器知道了你要做什麼,通過優化器知道了該怎麼做,於是就進入了執行 器階段,開始執行語句。開始執行的時候,要先判斷一下你有沒有執行的許可權,如果沒有,就會返 回沒有許可權的錯誤,如下所示 (在工程實現上,如果命中查詢快取,會在查詢快取返回結 果的時候,做許可權驗證。查詢也會在優化器之前呼叫 precheck 驗證許可權)。如果有許可權,就開啟表繼續執行。開啟表的時候,執行器就會根據表的引擎定義,去使用 這個引擎提供的介面。
比如我們下面的例子中的查詢語句:
select * from t where id=10;
id 字段沒有索引,那麼執行器的執行流程是這樣的:
呼叫 innodb 引擎介面取這個表的第一行,判斷 id 值是不是 10,如果不是則跳過,如 果是則將這行存在結果集中;
呼叫引擎介面取「下一行」,重複相同的判斷邏輯,直到取到這個表的最後一行
執行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結果集返回給客戶端。至此,這個語句就執行完成了。
redo log
當mysql有一條記錄需要更新的時候,innodb 引擎就會先把記錄寫到 redo log裡面,並更新記憶體,這個時候更新就算完成了。同時,innodb 引擎會在適當的時 候,將這個操作記錄更新到磁碟裡面,而這個更新往往是在系統比較空閒的時候做。有了 redo log,innodb 就可以保證即使資料庫發生異常重啟,之前提交的記錄都不會丟 失,這個能力稱為crash-safe.
2.binlog
redo log 是 innodb 引擎特有的日誌,而 server 層也有自己的日誌,稱為 binlog。
為什麼會有兩份日誌呢?
因為最開始 mysql 裡並沒有 innodb 引擎。mysql 自帶的引擎是 myisam,但是 myisam 沒有 crash-safe 的能力,binlog 日誌只能用於歸檔。而 innodb 是另乙個公司 以外掛程式形式引入 mysql 的,既然只依靠 binlog 是沒有 crash-safe 能力的,所 以 innodb 使用另外一套日誌系統——也就是 redo log 來實現 crash-safe 能力。
這兩種日誌有以下三點不同。
1. redo log 是 innodb 引擎特有的;binlog 是 mysql 的 server 層實現的,所有引擎 都可以使用。
2. redo log 是物理日誌,記錄的是「在某個資料頁上做了什麼修改」;binlog 是邏輯日 志,記錄的是這個語句的原始邏輯,比 如「給 id=2 這一行的 c 欄位加 1 」。
3. redo log 是迴圈寫的,空間固定會用完;binlog 是可以追加寫入的。「追加寫」是指 binlog 檔案寫到一定大小後會切換到下一 個,並不會覆蓋以前的日誌。
複習知識點
題目 class aclass bextends aclass cextends aclass dextends ba obj newd system.out.println obj instanceofb system.out.println obj instanceofc system.out....
知識點複習
scanf d用於輸入十進位制數 u無符號十進位制輸入 o用於輸入8進製數 c用於輸入單個字元 s用於輸入字串 非空格開始,空格結束,字串變數以 0 結尾 f,lf用於輸入實數,一般使用double,lf 表示對應的輸入量不賦給乙個變數 d printf d帶符號十進位制輸出 u無符號十進位制輸出 ...
Linux複習知識點(一)
linux 複習 1.linux基本操作 多使用者 命令進行互動 目錄結構 1 目錄結構 檔案系統 bin 命令 可執行程式 lib 庫檔案 etc 系統的配置檔案 boot 核心,與啟動有關的檔案 dev 裝置檔案 home 普通使用者的家目錄 mnt 臨時掛載點 proc 記憶體中程序的資訊 u...