事物級別
- 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), 可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數;