1. 程式人生 > >Mysql MyISAM與InnoDB 表鎖行鎖以及分庫分表優化

Mysql MyISAM與InnoDB 表鎖行鎖以及分庫分表優化

搜索 ash 能力 缺點 外部 加鎖 結構 create 主從

一、 兩種存儲引擎:MyISAM與InnoDB 區別與作用

1. count運算上的區別:

因為MyISAM緩存有表meta-data(行數等),因此在做COUNT(*)時對於一個結構很好的查詢是不需要消耗多少資源的。而對於InnoDB來說,則沒有這種緩存。

2. 是否支持事務和崩潰後的安全恢復:

MyISAM 強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但不提供事務支持。InnoDB 提供事務支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

3. 是否支持外鍵:

MyISAM不支持,而InnoDB支持。

?
1. 2 MyISAM特點(5.5 版本前默認引擎)
?

  1. MyISAM:只支持表級鎖,不支持行鎖。用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖 (讀取時對需要讀到的所有表加鎖,寫入時則對表加排他鎖;)

  2. 不支持事務

  3. 不支持外鍵

  4. 不支持崩潰後的安全恢復

  5. 在表有讀取查詢的同時,支持往表中插入新紀錄

  6. 支持BLOB和TEXT的前500個字符索引,支持全文索引

  7. 支持延遲更新索引,極大地提升了寫入性能

  8. 對於不會進行修改的表,支持 壓縮表 ,極大地減少了磁盤空間的占用

?
1.2.2 表鎖與行鎖 hang鎖

?

  • 計算機(Mysql)協調多個進程或線程並發訪問某一表或某行數據的機制
  1. 表鎖: 每次操作鎖住整張表。開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,並發度最低;

  2. 行鎖: 每次操作鎖住一行數據。開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,並發度最高;

?
1.3 InnoDB (5.5 版本後默認引擎
?
註意:InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

  1. 支持行鎖,采用MVCC來支持高並發,有可能死鎖
  2. 支持事務
  3. 支持外鍵
  4. 支持崩潰後的安全恢復
    不支持全文索引

?
1.4 綜上
所以:MyISAM更適合讀密集的表,而InnoDB更適合寫密集的的表。 在數據庫做主從分離的情況下,經常選擇MyISAM作為主庫的存儲引擎。

如果需要事務支持,並且有較高的並發讀取頻率(MyISAM的表鎖的粒度太大,所以當該表寫並發量較高時,要等待的查詢就會很多了),這時選InnoDB是不錯的。如果你的數據量很大(MyISAM支持壓縮特性可以減少磁盤的空間占用),而且不需要支持事務時,MyISAM是最好的選擇。

?
二、兩種數據結構的索引
?

哈希索引:

底層的數據結構是哈希表,因此在絕大多數需求為單條記錄查詢的時候,可以選擇哈希索引,查詢性能最快;其余大部分場景,建議選擇BTree索引。

B-Tree索引:下圖為B+Tree

技術分享圖片

  1. MyISAM: B+Tree葉節點的data域存放的是數據記錄的地址。在索引檢索的時候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其 data 域的值,然後以 data 域的值為地址讀取相應的數據記錄。這被稱為“非聚簇索引”。

  2. InnoDB: 其數據文件本身就是索引文件。相比MyISAM,索引文件和數據文件是分離的,其表數據文件本身就是按B+Tree組織的一個索引結構,樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這被稱為“聚簇索引(或聚集索引)”。而其余的索引都作為輔助索引(非聚集索引),輔助索引的data域存儲相應記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據主索引搜索時,直接找到key所在的節點即可取出數據;在根據輔助索引查找時,則需要先取出主鍵的值,在走一遍主索引。 因此,在設計表的時候,不建議使用過長的字段作為主鍵,也不建議使用非單調的字段作為主鍵,這樣會造成主索引頻繁分裂。

?
三、數據庫常見優化手段
?
當MySQL單表記錄數過大時,數據庫的CRUD性能會明顯下降
增加(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)

  1. 限定數據的範圍: 務必禁止不帶任何限制數據範圍條件的查詢語句。比如:我們當用戶在查詢訂單歷史的時候,我們可以控制在一個月的範圍內。;

  2. 讀/寫分離: 經典的數據庫拆分方案,主庫負責寫,從庫負責讀;

  3. 緩存: 使用MySQL的緩存,另外對重量級、更新少的數據可以考慮使用應用級別的緩存;

  4. 垂直分區:
    根據數據庫裏面數據表的相關性進行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。
    簡單來說垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表
    技術分享圖片

  • 垂直拆分的優點:
    可以使得行數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易於維護。

  • 垂直拆分的缺點:
    主鍵會出現冗余,需要管理冗余列,並會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加復雜;

  1. 水平分區:
    ?
    保持數據表結構不變,通過某種策略存儲數據分片。這樣每一片數據分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數據量。
    ?
    水平拆分是指數據表行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的數據拆成多張表來存放。
    技術分享圖片

水品拆分可以支持非常大的數據量。需要註意的一點是:分表僅僅是解決了單一表數據過大的問題,但由於表的數據還是在同一臺機器上,其實對於提升MySQL並發能力沒有什麽意義,所以 水品拆分最好分庫 。
水平拆分能夠 支持非常大的數據量存儲,應用端改造也少,但 分片事務難以解決 ,跨界點Join性能較差,邏輯復雜。

Mysql MyISAM與InnoDB 表鎖行鎖以及分庫分表優化