[TOC]
# innodb鎖的模式

## 悲觀鎖(多寫情況)
#### 1.是什么?
> 每次處理數據時, 都認為別人也會修改, 所以每次處理數據時, 先提前加鎖, 再處理;
## 樂觀鎖(多讀情況)
####  1.是什么?
> 每次處理數據時, 都認為別人不會修改, 所以每次處理數據時,
都不加鎖, 只是在更新數據時, 判斷下別人有沒有在此期間修改過數據;
####  2.兩種實現方式
####   2.1 \. 版本號機制
> 一般是在數據表中加上一個數據版本號version字段,表示數據被修改的次數,當數據被修改時,version值會加一。當線程A要更新數據值時,在讀取數據的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當前數據庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
####   2.2 \. CAS算法
> 即**compare and swap(比較與交換)**,是一種有名的**無鎖算法**。無鎖編程,即不使用鎖的情況下實現多線程之間的變量同步,也就是在沒有線程被阻塞的情況下實現變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。
## 共享鎖(讀鎖 s)
> 多個事務對于同一數據可以共享一把鎖,都能訪問到數據,但是只能讀不能修改
> 加鎖:? ?select? \* from tb\_student? where id = 1 **lock? in share mode**
釋放:? commit? /? rollback
## 排他鎖 (寫鎖 x):
> 排他鎖就是不能與其他所并存,如一個事務獲取了一個數據行的排他鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務是可以對數據就行讀取和修改。
> InnoDB引擎默認的修改數據語句,update,delete,insert都會自動給涉及到的數據加上排他鎖,select語句默認不會加任何鎖類型
> 加過排他鎖的數據行在其他事務種是不能修改數據的,也不能通過for update和lock in share mode鎖的方式查詢數據,但可以直接通過select ...from...查詢數據,因為普通查詢沒有任何鎖機制
> select? \*? from? tb\_student where id = 1?**?for update**
### 表鎖
> 加表鎖:? ? ? ?lock table \[tableName\] \[read | write\]
> 釋放表鎖:? ?unlock table
###意向鎖
表鎖和行鎖存在沖突,比如:
1. transactionA獲取了tableA中某一行的共享鎖,其它事務就不能再修改這行數據了
2. trsactionB如果獲取了tableA的表級排它鎖,就可以對tableA的所有數據修改
這里 transactionB的表鎖和transactionA的行鎖就是沖突的
意向鎖就是為了解決行鎖和表鎖的沖突,意向鎖本身也是表級別的鎖,事務在獲取行鎖前,必須先獲取相應的意向鎖,意向鎖相當于一個標記,用來顯示當前是否有事務鎖住了表中的某一行
事務在獲取表中某一行的 ?共享鎖 前必須先獲取到 意向共享鎖或者更高級別的鎖
事務在獲取表中某一行的 排它鎖 前必須先獲取到 意向排它鎖
#### 意向共享鎖(Is):
#### 意向排他鎖 (IX):

### 記錄鎖(Record Lock)
select \* from \[tb\_name\] where? ?id =? #{id}? for update
id列上有唯一索引,并且查詢條件可以唯一確定一條記錄,這時候innodb使用記錄鎖,只會鎖住查出來的這一行記錄
### 間隙鎖(Gap Lock):
> where后面的字段有索引,但不是唯一索引,或者使用了>,? <? 等范圍的查詢條件時,查詢條件范圍內的索引值之間的間隙會被加鎖,結果就是被加鎖的間隙之間不能插入索引值
> 區間是左開右閉的
> 在InnoDB下,間隙鎖的產生需要滿足三個條件:
* 隔離級別為RR
* 當前讀
* 查詢條件能夠走到索引
### 鎖(Next-key Lock)
是行鎖與間隙鎖的組合
# 死鎖
### 什么是死鎖?
> 當兩個事務都需要獲得對方持有的排他鎖才能完成事務,這樣就導致了循環鎖等待,也就是常見的死鎖類型
### 產生的原因?
> Mysql行級鎖并不是直接鎖記錄,而是鎖索引。索引分為主鍵索引和非主鍵索引兩種,如果一條sql語句操作了主鍵索引,那么Mysql就會鎖定這個主鍵索引,如果sql語句操作的是非主鍵索引,那么Mysql會先鎖定這個非主鍵索引,再去鎖定主鍵索引。
> 在UPDATE 和 DELETE操作時Mysql不僅會鎖定所有WHERE 條件掃描過得索引,還會鎖定相鄰的鍵值。
### 解決死鎖的方法?
> 1、? 數據庫參數
> 2、? 應用中盡量約定程序讀取表的順序一樣
> 3、? 應用中處理一個表時,盡量對處理的順序排序
> 4、? 調整事務隔離級別(避免兩個事務同時操作一行不存在的數據,容易發生死鎖)
### 死鎖的案例
> Test:(ID,STATE,TIME)? 主鍵索引:ID? 非主鍵索引:STATE
> 當執行"UPDATE? STATE =1011 WHERE STATE=1000"? 語句的時候會鎖定STATE索引,由于STATE 是非主鍵索引,所以Mysql還會去請求鎖定ID索引
> 當另一個SQL語句與語句1幾乎同時執行時:“UPDATE STATE=1010 WHERE ID=1”? 對于語句2 Mysql會先鎖定ID索引,由于語句2操作了STATE字段,所以Mysql還會請求鎖定STATE索引。這時。彼此鎖定著對方需要的索引,又都在等待對方釋放鎖定。所以出現了"死鎖"的情況。
# MVCC
* ## 是什么?
> `MVCC (Multiversion Concurrency Control)`?中文全稱叫多版本并發控制,是現代數據庫(包括?`MySQL`、`Oracle`、`PostgreSQL`?等)引擎實現中常用的處理讀寫沖突的手段,目的在于提高數據庫高并發場景下的吞吐性能。
* ## 實現流程?
####   1.update修改的實現流程
> 1. 通過主鍵(或隱藏主鍵 DB_ROW_ID), 對該行加排他鎖
> 2. 將這條記錄, 原封不到的放入`undo log`?中, 記做nudolog1;
> 3. 執行修改, 會產生新的 事務, 所以在`undo log`?中產生新的一條記錄,記做undolog2, 相比較undolog1, undolog2中會修改兩個值;
> 3.1 修改第一個值: 事務ID(DATA_TRX_ID), 將其改成新的事務ID(例如 原本nudolog1中該值是1 , 那么undolog2中改成2);
> 3.2 修改第二個值: 指向回滾段指針(DATA_ROLL_PRE), 將其值指向undolog1;
> 如果對該行記錄執行連續的update操作, 則重復上面2,3操作, 然后`undo log`?會形成鏈表, 遍歷這個鏈表可以看到這條記錄的變遷;
> 4. 記錄?`redo log`,包括?`undo log`?中的修改
####   2.delete修改的實現流程
####   3.insert修改的實現流程
* ## 如何實現一致性讀?
> 1.RU隔離級別下
> 直接讀版本的最新記錄就可以
> 2.RC 和 RR隔離級別下 (MVCC運行在這兩個級別下)
> 在?`SELECT`?數據時就會用到版本鏈, 但是要讀哪個版本下的記錄就要決定于 , `ReadView`(可讀視圖)了
> 3.S隔離級別下
> 是通過加鎖互斥來訪問數據的, 用不到MVCC
*
# 相關命令操作
- 簡介
- html
- js
- 正則表達式
- php
- 開發環境和配置
- PHP基礎
- 變量
- 數據類型
- 函數
- 常量
- 運算符
- 流程控制
- 文件
- 異常處理
- 高級
- 會話控制
- 面向對象
- 框架
- laravel
- ThinkPhp
- Yii 易
- Yaf 亞夫
- Swooole
- python
- 數據庫
- 基礎
- 索引
- 倒排索引
- 關聯sql
- 事務
- 鎖
- 優化
- 安全性
- 數據庫類型
- linux
- 基礎命令
- shell腳本
- 操作系統和網絡
- 版本控制器
- git
- git 命令行
- 小烏龜git的使用
- git 基礎命令
- svn
- svn 命令行
- 小烏龜svn的使用
- 網絡
- OSI七層模型
- 網絡協議
- https協議
- TCP UTP協議
- 數據結構和算法
- 算法
- 時間復雜度
- 空間復雜度
- 排序算法
- 查找算法
- 數據結構
- 系統設計和架構
- 緩存系統
- redis
- lua
- memcached
- redis與memcached的區別
- 消息隊列
- kafka
- 設計模式
- 單例模式
- 高并發和大流量設計
- 流量優化
- 前端優化
- web防盜鏈
- CDN加速
- 獨立的圖片服務器
- 服務器端
- 動態語言靜態化
- 并發處理
- 數據庫優化
- web服務器負載均衡
- 面試
- 項目整理
- novonordisk.micego.com
- nnm.micego.com
- www.dawang.tv
- lottery.3lotto.cn
- www.gpquan.cn
- in-tao.com
- 簡歷
- 面試問題
- 知識點
- 真題