Myisam引擎和InnoDB引擎
- mysql優先選擇使用innodb引擎,原因:支持事務,支持行級鎖,支持外鍵,高效處理併發以及併發帶來的一致性問題;
- Myisam的優勢: 查詢效率要高一些
兩者的區別類似於AMD和Intel的區別;
mysql執行sql過程
客戶端連接mysqld => 登錄鑑權 => 【開啓緩存 查看是否命中查詢緩存,直接返回】 => sql語句解析成sql解析樹 => 查詢語句預處理器,檢查解析樹是否合法 => 查詢優化器優化執行計劃(是否命中索引,如何查詢成本最小,性能最優) => 查詢執行引擎(innodb)返回數據
mysql事務
事務特點(ACID)
- 原子性(Atomicity): 一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
- 一致性(Consistency):在事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續數據庫可以自發性地完成預定的工作。
- 隔離性:數據庫允許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致數據的不一致。事務隔離分爲不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。mysql默認的事務隔離級別爲repeatable-read。
- 持久性:事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。
事務併發問題
- 髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據
- 不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。 => 解決辦法:鎖行
- 幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。 => 解決辦法:鎖表
事務隔離級別
- 讀未提交(Read uncommitted): 【事務a能讀到事務b未提交的修改】
- 讀提交(read committed): 寫數據只會鎖住相應的行,【事務a只能讀到事務b提交後(commit)的修改】
- 可重複讀(repeatable read): 如果檢索條件有索引(包括主鍵索引)的時候,默認加鎖方式是next-key 鎖;如果檢索條件沒有索引,更新數據時會鎖住整張表。一個間隙被事務加了鎖,其他事務是不能在這個間隙插入記錄的,這樣可以防止幻讀。【事務a在事務b執行過程中插入了一條新紀錄】。
- 串行化(Serializable): 讀寫數據都會鎖住整張表。
注: 隔離級別越高,越能保證數據的完整性和一致性,但是對併發性能的影響也越大。
MySQL事務隔離級別
事務隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交(read-uncommitted) | 是 | 是 | 是 |
讀提交(read-committed) | 否 | 是 | 是 |
可重複讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
Mysql鎖機制
概念
- 表鎖: 表鎖鎖住的是一整張表,表鎖是開銷最小的鎖策略。
- 行鎖: 行鎖鎖住的是表中的一行數據,行鎖是開銷最大的鎖策略【需要找到對應的行】,開銷大,加鎖慢,會產生死鎖,發生鎖衝突的概率最低,併發度也最高。【一般情況下儘量優先加行鎖,爲了提高併發】
- 共享讀鎖(S鎖): 由讀表操作加上的鎖,加鎖後其他用戶只能獲取該表或行的共享讀鎖,不能獲取排它寫鎖,也就是說只能讀不能寫。
- 排他寫鎖(X鎖): 由寫表操作加上的鎖,加鎖後其他用戶不能獲取該表或行的任何鎖 如果事務T對數據A加上排他寫鎖後,則其他事務不能再對A加任何類型的封鎖,不允許進行讀寫。獲准排他寫鎖的事務既能讀數據,又能修改數據, 粒度大,開銷小,加鎖快,不會出現死鎖,發出鎖衝突的概率最高,併發度最低。
- 死鎖: 多個進程互相等待對方鎖的釋放。 => 重啓對應的服務;
- 鎖衝突:一個進程等待另一個進程釋放需要的鎖;
- 悲觀鎖: 假定會發生併發衝突,屏蔽一切可能違反數據完整性的操作。
- 樂觀鎖: 假設不會發生併發衝突,只在提交操作時檢查是否違反數據完整性。