MyISAM和InnoDB的區別


MyISAM和InnoDB的差異

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

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

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

1.  表鎖差異

MyISAM

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

InnoDB

  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)         解決死鎖的方法:

      1、數據庫參數;

      2、 應用中盡量約定程序讀取表的順序一樣;

      3、 應用中處理一個表時,盡量對處理的順序排序;

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

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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM