關于Mysql(5.6)的一些思考

事物級別

  • MySQL 默認事物級別是可重復讀;Oracle默認為讀已提交
>> SELECT @@global.tx_isolation; 
>> REPEATABLE-READ
  • 事務級別的優先級:
    1:讀未提交
直接返回記錄行上的最新記錄;沒有視圖的概念

2:讀已提交

視圖是在每個sql語句開始時創建的。

3:可重復讀

事物開啟會建立視圖,依據視圖做到事務隔離

4:串行化

讀寫均加鎖來實現

5:事務隔離的實現-可重復度級別


回滾日志.png
實際上每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態的值。建議盡量不要寫長事物。

6:查找時間超過 60s的事物

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>=60;

7: 沒有特殊邏輯;盡量不要對Read進行事務管理
性能測試如下:https://www.percona.com/blog/2019/07/15/mysql-the-impact-of-transactions-on-query-throughput/

Impact-of-Transactions.png

一條查詢SQL的執行計劃

邏輯架構圖.png

Mysql大致可以分為Server層和存儲引擎層
1:連接器

負責跟客戶端建立連接、獲取權限、維持和管理連接:
例如如下:
mysql -h$ip -P$port -u$user -p
mysql> show processlist;
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
| Id  | User        | Host                                        | db          | Command | Time   | State                                                                       | Info             |
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
|   1 | system user |                                             | NULL        | Connect | 173583 | Waiting for master to send event                                            | NULL             |
|   2 | system user |                                             | NULL        | Connect |     -1 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL             |
|  63 | demo        | bjwfj-67p109-mediaforce-42.bfdabc.com:61820 | bfd_mf_data | Sleep   |     16 |                                                                             | NULL             |
| 118 | root        | localhost                                   | NULL        | Query   |      0 | init                                                                        | show processlist |
+-----+-------------+---------------------------------------------+-------------+---------+--------+-----------------------------------------------------------------------------+------------------+
對 druid中鏈接數進行查看如下:
當前連接池中的數目:1
這里涉及到一個問題,如果客戶端太長時間沒動靜,連接器會自動斷開,這個參數是由參數:wait_timeout控制,默認是 8 小時。目前業務端是基于連接池的,本省就是就可以控制connection的活躍數目;所以可將該值調整為 24小時。避免 Lost Connection to Mysql server during query 的異常;當然這里也存在問題;如果客戶端Connection異常關閉,那么Mysql 端的連接也去就無法釋放;所以有更加優雅的方式:
1: 定期斷開長連接
2: Mysql 5.7+ 支持 mysql_reset_connection 來重新初始化鏈接

2:查詢緩存

緩存的 key就是查詢語句,Value就是緩存的行記錄。但是大多數情況下不建議使用查詢緩存,因為查詢緩存往往弊大于利。緩存失效非常頻繁,只要對一個表的更新,這表上所有的查詢緩存都會清空。Mysql提供啦一種按需使用的方式,可以將 query_cache_type設置為DEMAND,這樣默認的查詢語句都不會使用緩存;可以顯示指定SQL_CACHE 參數:
mysql> select SQL_CACHE * from T where ID=10;
Mysql8.0 已徹底將該功能移除并廢棄掉

3:分析器

分析器做的就是詞法分析,檢驗sql語句的合法性

4:優化器

優化器是在表里面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連接順序。

5:執行器

MySQL 通過分析器知道了你要做什么,通過優化器知道了該怎么做,于是就進入了執行器階段,開始執行語句。如果有權限,就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。經常看到的rows_examined 就是執行中的指標。

一條更新Sql的執行計劃

1:redo log


redo log.png
 redo log 是innoDB引擎特有的日志。redo log其實就是Mysql中經常提到的WAL(Write-Ahead Logging)技術;關鍵點就是先寫日志,在寫磁盤,這樣就大大降低啦磁盤的IO成本、查找成本。

2: binlog
binlog(歸檔日志)服務于server層,是邏輯日志,記錄的是該語句的原始邏輯,同時是可以追加寫;達到一定文件大小后會切換到下一個。
3:update 執行流程圖


update流程圖.png
這個就涉及到Mysql的兩階段提交事務

索引

1: 覆蓋索引

目的是優化索引查詢; 減少回表次數
eg:
select id from t where index_age between 2 and 5; # 查詢的Id已經在索引index_age樹上,不需要回表
同時假如你的業務有大量的類似于:依據 身份證號查找姓名;其實可以 為 身份證號 + 姓名為聯合索引;極大的減少回表需求 

2: 最左前綴原則

最左前綴原則的實現是依據 B+樹索引來實現的
(name,age)索引示意圖.jpg

3: 索引下推
而 MySQL 5.6 引入的索引下推優化(index condition pushdown), 可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。