============================================
MySQL學習筆記【第四部分】
============================================
一. 事務
1.概述
數據庫操作的最小工作單元,是作爲單個邏輯工作單元執行的一系列操作; 事務是一組不可再分割的操作集合(工作邏輯單元)
2.事務的ACID特性
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔離性(Isolation)
- 持久性(Durability)
3.事務併發帶來的問題
- 髒讀
- 不可重複讀
- 幻讀
4.事務隔離級別
- Read Uncommitted(未提交讀) —解決併發問題【事務未提交對其它事務也是可見的,髒讀】
- Read Committed(提交讀) —解決髒讀問題【一個事務開始之後,只能看到自己提交事務所做的修改,不可重複讀】
- Repeatable Read(可重複讀) —解決不可重複讀問題【在同一個事務中多次讀取同樣的數據結果一樣的,未定義解決幻讀問題】
- Serialiazable(串行化) —解決所有問題【最高的隔離級別,通過強制事務的串行執行】
5.InnoDB引擎對隔離級別的支持程度
二. 鎖
1.理解表鎖、行鎖
2.InnoDB鎖類型
- 共享鎖(行鎖):Shared Locks
- 排它鎖(行鎖):Exclusive Locks
- 意向共享鎖(表鎖):Intension Shared Locks
- 意向排它鎖(表鎖):Intension Exclusive Locks
- 自增鎖:AUTO-INC Locks
行鎖算法:
- 記錄鎖 Record Locks
- 間隙鎖 Gap Locks
- 臨鍵鎖 Next-key Locks
3.共享鎖、排它鎖
共享鎖:
共享鎖又稱爲讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務對於同一數據可以共享一把鎖,都能訪問到數據,但是隻能讀不能修改。
加鎖釋鎖方式:
select * from users WHERE id=1 LOCK IN SHARE MODE;
commit/rollback
排它鎖:
排它鎖又稱爲寫鎖,簡稱X鎖,排它鎖不能與其他鎖共存,如一個事務獲得了一個數據行的排它鎖,其他事務就不能在獲取該行的鎖(共享鎖,排它鎖),只有獲取了排它鎖的事務是可以對數據進行讀取和修改的(其它事務讀取數據可來自於快照)
加鎖釋鎖方式:
delete / update / insert 默認加上X鎖
SELECT * FROM table_name WHERE ... FOR UPDATE
commit/rollback
InnoDb-行鎖到底鎖了什麼
InnoDB的行鎖是通過給索引上的索引項加鎖來實現的。
只有通過索引條件進行數據檢索,InnoDB才使用行級鎖,否則,InnoDB 將使用表鎖(鎖住索引的所有記錄)
表鎖:lock tables xx read/write;
4.意向共享鎖(IS)、意向排它鎖(IX)
意向共享鎖:
表示事務準備給數據行加入共享鎖,即一個數據行加共享鎖前必須先取得該表的IS鎖, 意向共享鎖之間是可以相互兼容的。
意向排它鎖:
表示事務準備給數據行加入排他鎖,即一個數據行加排他鎖前必須先取得該表的IX鎖, 意向排它鎖之間是可以相互兼容的。
意義
當事務想去進行鎖表時,可以先判斷意向鎖是否存在,存在時則可快速返回該表不能 啓用表鎖
意向鎖(IS、IX)是InnoDB數據操作之前自動加的,不需要用戶干預
5.自增鎖AUTO-INC Locks
針對自增列自增長的一個特殊的表級別鎖
show variables like 'innodb_autoinc_lock_mode';
默認取值1,代表連續,事務未提交ID永久丟失
6.記錄鎖(Record)、間隙鎖(Gap)、臨鍵鎖(Next-Key)
Next-Key Locks
鎖住記錄+區間(左開右閉)
當sql執行按照索引進行數據的檢索時,查詢條件爲範圍查找(between and、<、>等)並有數 據命中則此時SQL語句加上的鎖爲Next-key locks,鎖住索引的記錄+區間(左開右閉)
Gap Locks
鎖住數據不存在的區間(左開右開)
當sql執行按照索引進行數據的檢索時,查詢條件的數據不存在,這時SQL語句加上的鎖即爲 Gap locks,鎖住索引不存在的區間(左開右開)
Record Locks
鎖住具體的索引項
當sql執行按照唯一性(Primary key、Unique key)索引進行數據的檢索時,查詢條件等值匹 配且查詢的數據是存在,這時SQL語句加上的鎖即爲記錄鎖Record locks,鎖住具體的索引項
7.解決髒讀、不可重複讀、幻讀
1 利用X鎖解決髒讀
2 利用S鎖解決不可重複讀
3 利用Next-Key解決幻讀
8.死鎖
死鎖介紹:
- 多個併發事務(兩個以上)
- 每個事務都持有鎖(或者是已經在等待鎖)
- 每個事務都需要再繼續持有鎖
- 事務之間產生加鎖的循環依賴,形成死鎖
死鎖的避免:
- 類似的業務邏輯以固定的順序訪問表和行。
- 大事務拆小。大事務更傾向於死鎖,如果業務允許,將大事務拆小。
- 在同一個事務中,儘可能做到一次鎖定所需要的所有資源,減少死鎖概 率。
- 降低隔離級別,如果業務允許,將隔離級別調低也是較好的選擇
- 爲表添加合理的索引。可以看到如果不走索引將會爲表的每一行記錄添 加上鎖(或者說是表鎖)
9.MVCC
查看MySQL的設置的事務隔離級別
select global.@@tx_isolation;
select @@tx_isolation;
MVCC概述
多版本併發控制(Multiversion concurrency control),併發訪問(讀或寫)數據庫時,對正在事務內處理的數據做 多版本的管理。以達到用來避免寫操作的堵塞,從而引發讀操 作的併發問題。
MVCC邏輯流程-插入
MVCC邏輯流程-刪除
MVCC邏輯流程-修改
MVCC邏輯流程-查詢
Undo log
undo意爲取消,以撤銷操作爲目的,返回指定某個狀態的操作undolog指事務開始之前,在操作任何數據之前,首先將需操作的數據備份到一個地方(UndoLog)
UndoLog是爲了實現事務的原子性而出現的產物
UndoLog實現事務原子性
事務處理過程中如果出現了錯誤或者用戶執行了ROLLBACK語句,Mysql可以利用UndoLog中的備份將數據恢復到事務開始之前的狀態
UndoLog在Mysqlinnodb存儲引擎中用來實現多版本併發控制
Undolog實現多版本併發控制:
事務未提交之前,Undo保存了未提交之前的版本數據,Undo中的數據可作爲數據舊版本快照供其他併發事務進行快照讀
快照讀:
SQL讀取的數據是快照版本,也就是歷史版本,普通的SELECT就是快照讀
innodb快照讀,數據的讀取將由cache(原本數據)+undo(事務修改過的數據)兩部分組成
當前讀:
SQL讀取的數據是最新版本。通過鎖機制來保證讀取的數據無法通過其他事務進行修改UPDATE、DELETE、INSERT、SELECT…LOCKINSHAREMODE、SELECT…FORUPDATE都是當前讀。
Redo log
Redo,顧名思義就是重做。以恢復操作爲目的,重現操作;
Redolog指事務中操作的任何數據,將最新的數據備份到一個地方(RedoLog)Redolog的持久:
不是隨着事務的提交才寫入的,而是在事務的執行過程中,便開始寫入redo中。具體的落盤策略可以進行配置
RedoLog是爲了實現事務的持久性而出現的產物
Undolog實現多版本併發控制:
事務未提交之前,Undo保存了未提交之前的版本數據,Undo中的數據可作爲數據舊版本快照供其他併發事務進行快照讀
Redo log補充
-
指定Redolog記錄在{datadir}/ib_logfile1&ib_logfile2可通過innodb_log_group_home_dir配置指定目錄存儲
-
一旦事務成功提交且數據持久化落盤之後,此時Redolog中的對應事務數據記錄就失去了意義,所以Redolog的寫入是日誌文件循環寫入的
-
指定Redolog日誌文件組中的數量innodb_log_files_in_group默認爲2
-
指定Redolog每一個日誌文件最大存儲量innodb_log_file_size默認48M指定Redolog在cache/buffer中的buffer池大小innodb_log_buffer_size默認16M
-
Redobuffer持久化Redolog的策略,Innodb_flush_log_at_trx_commit:
-
取值0每秒提交Redobuffer–>RedologOScache–>flushcachetodisk[可能丟失一秒內的事務數據]
-
取值1默認值,每次事務提交執行Redobuffer–>RedologOScache–>flushcachetodisk [最安全,性能最差的方式]
-
取值2每次事務提交執行Redobuffer–>RedologOScache再每一秒執行->flushcacheto disk操作
3.配置優化
MySQL服務器參數類型
基於參數的作用域:
全局參數setglobalautocommit=ON/OFF;
會話參數(會話參數不單獨設置則會採用全局參數):setsessionautocommit=ON/OFF;
注意:
全局參數的設定對於已經存在的會話無法生效
會話參數的設定隨着會話的銷燬而失效
全局類的統一配置建議配置在默認配置文件中,否則重啓服務會導致配置失效
mysql--help尋找配置文件的位置和加載順序
Defaultoptionsarereadfromthefollowingfilesinthegivenorder:
/etc/my.cnf/etc/mysql/my.cnf/usr/etc/my.cnf~/.my.cn
fmysql--help|grep-A1'Defaultoptionsarereadfromthefollowing filesinthegivenorder'
全局配置文件配置
最大連接數配置:max_connections
系統句柄配置:/etc/security/limits.confulimit-a
MySQL句柄數配置:/usr/lib/systemd/system/mysqld.service
常見全局配置文件配置
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
max_connections=2000
lower_case_table_names=0#表名區分大小寫
server-id=1
tmp_table_size=16
Mtransaction_isolation=REPEATABLE-READ
ready_only=1
...
MySQL內存參數配置
每一個connection內存參數配置:
- sort_buffer_sizeconnection排序緩衝區大小:建議256K(默認值)->2M之內當查詢語句中有需要文件排序功能時,馬上爲connection分配配置的內存大小
- join_buffer_sizeconnection關聯查詢緩衝區大小:建議256K(默認值)->1M之內當查詢語句中有關聯查詢時,馬上分配配置大小的內存用這個關聯查詢,所以有可能在一個查詢語句中會分配很多個關聯查詢緩衝區
- 上述配置4000連接佔用內存:4000*(0.256M+0.256M)=2G
Innodb_buffer_pool_size
innodbbuffer/cache的大小(默認128M)Innodb_buffer_pool
- 數據緩存
- 索引緩存
- 緩衝數據
- 內部結構
大的緩衝池可以減小多次磁盤I/O訪問相同的表數據以提高性能
參考計算公式:Innodb_buffer_pool_size=(總物理內存-系統運行所用-connection所用)*90%
MySQL其他參數配置
-
wait_timeout:服務器關閉非交互連接之前等待活動的秒數
-
innodb_open_files:限制Innodb能打開的表的個數
-
innodb_write_io_threads:innodb使用後臺線程處理innodb緩衝區數據頁上的讀寫I/O(輸入輸出)請求
-
innodb_read_io_threads:innodb使用後臺線程處理innodb緩衝區數據頁上的讀寫I/O(輸入輸出)請求
-
innodb_lock_wait_timeout:InnoDB事務在被回滾之前可以等待一個鎖定的超時秒數
4.數據庫設計
注:希望讀者如果有時間的話可以去了解一下58同城的30條軍規