MyISAM和InnoDB的區別

MyISAM和InnoDB的差別

Mysql支持不少表類型的表(即存儲引擎),如MyISAM、InnoDB、Memory、Archive、Example等,主要介紹兩種MyISAM和InnoDB。mysql

MyISAM是默認表類型,基於ISAM(Indexed Sequential Access Method索引順序訪問方法),它是存儲記錄和文件的標準方法,不是事務安全的,不支持外鍵,若是有大量的select,MyISAM比較合適。MyISAM表示獨立於操做系統以外的,通俗點說就是你能夠很輕鬆的將MyISAM表從windows移植到linux或者從linux移植到windows。linux

InnoDB支持事務安全,支持外鍵、行鎖,事務是它的最大優勢,若是有大量的insert和update,建議用InnoDB,特使是針對高併發和QPS(query per second)較高的狀況。sql

1.  表鎖差別

MyISAM

  MyISAM只支持表鎖,在select、insert、update、delete都會鎖表,開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的機率最高,併發量最低。數據庫

InnoDBwindows

  InnoDB支持事務和行鎖,開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的機率小,併發度最高。安全

  1>     事務的ACID屬性併發

    a)         原子性(Atomicity):原子性是指事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生。函數

    b)         一致性(Consistency):事務先後數據的完整性必須保持一致。高併發

    c)         隔離性(Isolation):事務的隔離性是多個用戶併發訪問數據庫時,數據庫爲每個用戶開啓的事務,不能被其餘事務的操做數據所幹擾,多個併發事務之間要相互隔離。性能

    d)         持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響。

  2>     併發事務帶來的問題

    a)         髒讀:一個事務修改了還沒提交,另外一個事務就讀了。

    b)         不可重複讀:一個事務兩次讀取數據之間,另外一個事務修改了數據。

    c)         幻讀:一個事務兩次讀取數據之間,另外一個事務新增了數據。

    d)         丟失修改(更新丟失):兩個事務同時修改每一個數據,一個事務的提交破壞了另外一個事務的修改。例如,T1讀A修改成A-1,T2也讀A修改成A-1(實際上T2讀A-1修改成A-2)。

  3>     事務隔離級別

 

隔離級別

讀數據一致性

併發反作用

髒讀

不可重複讀

幻讀

未提交讀

(Read uncommitted)

最低級別,不讀物理上損壞的數據

已提交讀

(Read committed)

語句級

可重複讀

(Repeatable read)

事務級

可序列化

(Serializable)

最高級別,

事務級

    查看mysql的默認事務隔離級別「show global variables like ‘tx_isolation’;」

  4>     InnoDB的行鎖模式有如下幾種:共享鎖,排他鎖,意向共享鎖(表鎖),意向排他鎖(表鎖),間隙鎖。

    注意:當語句沒有使用索引,InnoDB不能肯定操做的行,這個時候就使用的意向鎖,也就是表鎖。

  5>     關於死鎖

    a)         什麼是死鎖?當兩個事務都須要得到對方持有的排他鎖才能完成事務,這樣就致使了循環鎖等待,也就是常見的死鎖類型。

    b)         解決死鎖的方法:

      一、數據庫參數;

      二、 應用中儘可能約定程序讀取表的順序同樣;

      三、 應用中處理一個表時,儘可能對處理的順序排序;

      四、 調整事務隔離級別(避免兩個事務同時操做一行不存在的數據,容易發生死鎖)。

2.  數據庫文件差別

MyISAM

  MyISAM屬於堆表。

  1>     在磁盤上存儲有3個文件,每一個文件以表名爲開頭。

    .frm用於存儲表的定義

    .MYD用於存放表的數據

    .MYI用於存放表的索引

  2>     在mysql中能夠建立3種MyISAM格式的表——靜態、動態和壓縮。格式不須要單獨指定,mysql會根據表結構自動選擇最合適的格式。

    a)         MyISAM靜態:若是表的每一個字段的數據類型的定義都是使用靜態的(如char),mysql就會自動使用靜態MyISAM格式,這種類型格式的表的性能是很高的,也就是查詢更新用的時間不多,但要知道這是在犧牲空間爲代價。由於每一列都要分配最大的空間,即便有部分空間沒有用到,這就使得靜態的表所佔的空間會比較大。

    b)         MyISAM動態:若是表的每一個字段的數據類型的定義都是使用動態的(如varchar),mysql就會自動使用動態MyISAM格式,這種類型格式的表的性能會有所降低,可是它的空間佔有要比靜態的少不少。

    c)          MyISAM壓縮:若是有一張表在設計之初只賦予了它讀的使命,就能夠用MyISAM壓縮表,在相同的配置下,它的性能是最快的。

InnoDB

  InnoDB屬於索引組織表。

  InnoDB有兩種存儲方式,共享表空間存儲和多表空間存儲,兩種存儲方式的表結構和MyISAM同樣,以表名開頭,擴展名是.frm。

  若是使用共享表空間,那麼全部表的數據文件和索引文件都保存在一個表空間裏,一個表空間能夠有多個文件,經過innodb_data_file_path和innodb_data_home_dir參數設置共享表空間的位置和名字,通常共享表空間的名字叫ibdata1-n。

  若是使用多表空間,那麼每一個表都有一個表空間文件用於存儲每一個表的數據和索引,文件名以表名開頭,以.ibd爲擴展名。

3.  索引差別

關於自動增加

MyISAM引擎的自動增加列必須是索引,若是是組合索引,自動增加能夠不是第一列,他能夠根據前面幾列進行排序後遞增。

InnoDB引擎的自動增加列必須是索引,若是是組合索引也必須是組合索引的第一列。

關於主鍵

MyISAM容許沒有任何索引和主鍵的表存在,MyISAM的索引都是保存行的地址。

InnoDB引擎若是沒有設定主鍵或者非空惟一索引,就會自動生成一個6字節的主鍵(用戶不可見),InnoDB的數據是主索引的一部分,附加索引保存的是主索引的值。

關於count()函數

MyISAM保存有表的總行數,若是select count(*) from table;會直接取出出該值。

InnoDB沒有保存表的總行數,若是使用select count(*) from table;就會遍歷整個表,消耗至關大,可是在加了wehre 條件後,MyISAM和InnoDB處理的方式都同樣。

全文索引

MyISAM支持 FULLTEXT類型的全文索引。

InnoDB不支持FULLTEXT類型的全文索引,可是InnoDB可使用sphinx插件支持全文索引,而且效果更好。(sphinx   是一個開源軟件,提供多種語言的API接口,能夠優化mysql的各類查詢)。

delete from table

使用這條命令時,InnoDB不會重新創建表,而是一條一條的刪除數據,在InnoDB上若是要清空保存有大量數據的表,最好不要使用這個命令。(推薦使用truncate table,不過須要用戶有drop此表的權限)。

索引保存位置

MyISAM的索引以表名+.MYI文件分別保存。

InnoDB的索引和數據一塊兒保存在表空間裏。

4.  幾點注意事項

  1. 能夠用 show create table tablename 命令看錶的引擎類型。

  2. 對不支持事務的表作start/commit操做沒有任何效果,在執行commit前已經提交。

  3. 能夠執行如下命令來切換非事務表到事務(數據不會丟失),InnoDB表比MyISAM表更安全:alter table tablename type=innodb;或者使用 alter table tablename engine = innodb;

  4. 默認innodb是開啓自動提交的,若是你按照MyISAM的使用方法來編寫代碼頁不會存在錯誤,只是性能會很低。如何在編寫代碼時候提升數據庫性能呢?

    1>       儘可能將多個語句綁到一個事務中,進行提交,避免屢次提交致使的數據庫開銷。

    2>       在一個事務得到排他鎖或者意向排他鎖之後,若是後面還有須要處理的sql語句,在這兩條或者多條sql語句之間程序應儘可能少的進行邏輯運算和處理,減小鎖的時間。

    3>       儘可能避免死鎖。

    4>       sql語句若是有where子句必定要使用索引,儘可能避免獲取意向排他鎖。

    5>       針對開發,通常日誌表之類的都是不修改的,能夠用MyISAM,而其餘表要用到事務,要頻繁修改的能夠用InnoDB。

相關文章
相關標籤/搜索