mysql事務(wù)
什么是事務(wù)
事務(wù)就是數(shù)據(jù)庫操作的最小單元。一個事務(wù)里面包含諾干邏輯要么全部成功要么全部失敗。事務(wù)是一組不可
再分割的操作集合。
事務(wù)的四大特性
1. 原子性: 事務(wù)包含的操作邏輯是不可再分的。要么全部成功。要么全部失敗
2. 一致性: 是對數(shù)據(jù)的可見性的約束,就是所有數(shù)據(jù)要么是事務(wù)開始前的樣子.要么全是結(jié)束的樣子,不
存在中間過渡是的數(shù)據(jù)。
3. 隔離性: 事務(wù)與事務(wù)之間是不受影響的。
4. 持久性: 事務(wù)一旦提交,那么它對數(shù)據(jù)庫的改變應(yīng)該是永久的。接下來的操作或者故障不會對其有影響。
事務(wù)的隔離級別
1. 讀未提交: 事務(wù)可以看見其他的事務(wù)還沒提交的修改. 比如一個事務(wù)a在對一行數(shù)據(jù)進(jìn)行修改,修改完后又刪除.
這整個過程對于別的事務(wù)來說都是透明的.這個級別的事務(wù)就基本沒有隔離性.
2. 讀以提交: 事務(wù)只能夠看到其他的事務(wù)已經(jīng)提交后的修改,當(dāng)前的事務(wù)運(yùn)行的時候可能會有多個事務(wù)已經(jīng)對某行
數(shù)據(jù)進(jìn)行了修改,并且已經(jīng)提交,所以多次查詢同一行的數(shù)據(jù)可能會不一樣.所以又被成為"不可重復(fù)讀".
3. 可重復(fù)讀: 事務(wù)在這個級別有數(shù)據(jù)版本控制,只會看到事務(wù)一開始的數(shù)據(jù)版本,所以數(shù)據(jù)不管讀多少次都是一樣的
是innodb的默認(rèn)級別.
4. 串行化: 事務(wù)完全串行的執(zhí)行.隔離級別最高,但是性能很差.
臟讀,不可重復(fù)讀,幻讀分別是什么
* 臟讀:事務(wù)a對數(shù)據(jù)庫進(jìn)行了修改還沒提交, 這個數(shù)據(jù)被事務(wù)b看到了并且使用,事務(wù)a因為一些原因撤銷了數(shù)據(jù),事務(wù)
b就相當(dāng)于發(fā)生了臟讀.
* 不可重復(fù)讀:事務(wù)a在運(yùn)行的時候可能會因為有多個事務(wù)的提交而對同一行數(shù)據(jù)進(jìn)行查詢多次結(jié)果不一樣.
* 幻讀:當(dāng)事務(wù)a查找多行數(shù)據(jù)的時候,可能會因為事務(wù)b的插入或者刪除而影響到.
| 隔離級別 |
臟讀 |
不可重復(fù)讀 |
幻讀 |
| 讀未提交 |
會 |
會 |
會 |
| 讀以提交 |
不會 |
會 |
會 |
| 可重復(fù)讀 |
不會 |
不會 |
會 |
| 串行化 |
不會 |
不會 |
不會 |
mysql不同級別的事務(wù)是怎么實現(xiàn)的
原子性:首先事務(wù)的原子性規(guī)定了事務(wù)要么全部成功要么全部失敗. 這是通過mysql的undo log 來實現(xiàn)的.舉個例子
當(dāng)事務(wù)a對行數(shù)據(jù)加了5,undo log就會生成一個減5的log.當(dāng)事務(wù)執(zhí)行到一半失敗了進(jìn)行回滾 就會運(yùn)行undo log
上的相關(guān)sql.
持久性:事務(wù)一旦提交數(shù)據(jù)就會生效,即使數(shù)據(jù)庫崩潰數(shù)據(jù)也不會丟失,這是因為mysql在提交的那一刻就sql語句就已
經(jīng)被記錄在redo log里.
隔離性:級別越低的隔離性所能夠承受的并發(fā)越高.不同的隔離性的實現(xiàn)其實就是(讀寫鎖和mvcc的不同運(yùn)用).首先最
低級別的讀未提交允許同一時間讀寫并行,同一時間一行數(shù)據(jù)只能被一個事務(wù)修改.正因為讀不加鎖,所以會出現(xiàn)臟讀的
情況.讀已提交: 事務(wù)中每次查詢都會生成一個數(shù)據(jù)版本,所以每次查詢都會讀到當(dāng)前最新的數(shù)據(jù),可重復(fù)讀:事務(wù)一開
始的時候就會生成一個數(shù)據(jù)版本號,所以不管數(shù)據(jù)怎么查都是查到指定版本數(shù)據(jù)。串行化:所有事務(wù)按照順序執(zhí)行。
mysql索引
什么是索引
索引是對數(shù)據(jù)庫表中的一列或多列的值進(jìn)行排序的一種結(jié)構(gòu),使用索引可以提高數(shù)據(jù)庫的查詢速度。索引是一個單獨的
存儲在磁盤上的數(shù)據(jù)庫結(jié)構(gòu),它們包含著對數(shù)據(jù)庫表里所有記錄的引用指針。
hash和b+ tree索引的優(yōu)劣
* hash索引只能精確查找做等值查詢,不能范圍查找,查找速度比 b+tree速度快很多.hash索引占用磁盤空間較大因為
有很多沒有命中的hash槽浪費(fèi)了空間。
* b+tree 支持聯(lián)合索引的最左匹配原則。支持模糊查找。范圍查找。一般情況下比hash速度慢,但是性能穩(wěn)定。
聚簇索引和覆蓋索引和回表
* 聚簇索引:就是索引最終直接指向整行數(shù)據(jù)。一般就是主鍵索引。如果沒有設(shè)置主鍵,innodb底層會選擇一個唯一
的非空的索引代替。如果沒有這樣的索引,innodb就會隱式的定義一個主鍵來作為聚簇索引。當(dāng)走這個索引查詢數(shù)劇
就只需要查詢完成就能夠獲得到目標(biāo)數(shù)據(jù)。
* 回表:當(dāng)sql走的不是聚簇索引的時候,該索引的葉子指向聚簇索引的id。mysql會通過當(dāng)前索引找到主鍵id。然后
拿到主鍵id去查詢主鍵索引。這個過程就稱之為回表,回表的話相當(dāng)于要走多個索引性能相對來說會慢點。
* 覆蓋索引:舉個例子 索引a 是字段a,b的聯(lián)合索引,如果一個 sql語句通過 索引a 查找字段a,b 。那么當(dāng)前的索
引已經(jīng)能夠查到所需要的數(shù)據(jù),所以就不需要回表查詢主鍵索引。
為什么選b+tree 作為索引的數(shù)據(jù)結(jié)構(gòu)
* b+ tree 的節(jié)點會存多個子節(jié)點,比起b tree 。b+ tree的數(shù)據(jù)全部存在葉子節(jié)點,非葉子節(jié)點只會存鍵。這樣
能夠存更多的關(guān)系數(shù)據(jù)。能夠更快的命中。樹高越低,磁盤io次數(shù)越少。b+樹的樹高 < b樹高 < 平衡二叉樹
* 更加適合范圍查找:在b樹進(jìn)行范圍查找是,要先找到查找的下限,然后對b樹進(jìn)行中序遍歷,直到找到查找的上限,
而b+樹的范圍查找,只需要對鏈接進(jìn)行遍歷即可。
* b tree 的查詢復(fù)雜度在 1 到樹高之間,而b+樹的查詢復(fù)雜度穩(wěn)定為樹高,因為所有數(shù)據(jù)節(jié)點都在葉子節(jié)點。
存儲引擎 MYISAM 和 INNODB 的區(qū)別
1. myisam 只支持表鎖,innodb支持行級鎖
2. myisam 不支持事務(wù), innodb支持
3. myisam 的表結(jié)構(gòu) 數(shù)據(jù) 索引是單獨存放的。innodb是索引和數(shù)據(jù)是放一起的
4. select count(*) from table 的時候myisam 不需要遍歷整表因為它對總行數(shù)有保存,innodb 需要遍歷。
5. myisam支持全文索引,innodb不支持。
Mysql死鎖
原因
多個事務(wù)在不同的資源占用后,并且請求對方占用的資源。并且不釋放。導(dǎo)致邏輯卡死。
死鎖檢測
innodb能檢測到死鎖的循環(huán)依賴,并立即返回錯誤,但是涉及到外部鎖,或者表鎖的情況下,innodb不能完全檢測
到。需要設(shè)置鎖等待超時時間 innodb_lock_wait_timeout來解決。
死鎖恢復(fù)
死鎖發(fā)生后只有部分或者完全回滾其中一個事務(wù),才能打破死鎖。innodb 現(xiàn)在就是將持有最少的行級排它鎖的事務(wù)
進(jìn)行回滾。
myisam會不會產(chǎn)生死鎖
不會。因為myiasm在事務(wù)一開始的時候就會先獲取自己所需要的所有鎖。所以不會發(fā)生死鎖的情況。
innodb死鎖避免
1. 可以在事務(wù)一開始的時候先嘗試獲得所有需要的鎖。獲得了再進(jìn)行操作。`SELECT ... FOR UPDATE`
2. 不同的事務(wù)盡量以相同的順序訪問表。這樣加鎖流程也會一樣。也會降低死鎖產(chǎn)生的機(jī)會
3. 改變事務(wù)隔離級別