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
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) 解決死鎖的方法:
一、數據庫參數;
二、 應用中儘可能約定程序讀取表的順序同樣;
三、 應用中處理一個表時,儘可能對處理的順序排序;
四、 調整事務隔離級別(避免兩個事務同時操做一行不存在的數據,容易發生死鎖)。
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有兩種存儲方式,共享表空間存儲和多表空間存儲,兩種存儲方式的表結構和MyISAM同樣,以表名開頭,擴展名是.frm。
若是使用共享表空間,那麼全部表的數據文件和索引文件都保存在一個表空間裏,一個表空間能夠有多個文件,經過innodb_data_file_path和innodb_data_home_dir參數設置共享表空間的位置和名字,通常共享表空間的名字叫ibdata1-n。
若是使用多表空間,那麼每一個表都有一個表空間文件用於存儲每一個表的數據和索引,文件名以表名開頭,以.ibd爲擴展名。
MyISAM引擎的自動增加列必須是索引,若是是組合索引,自動增加能夠不是第一列,他能夠根據前面幾列進行排序後遞增。
InnoDB引擎的自動增加列必須是索引,若是是組合索引也必須是組合索引的第一列。
MyISAM容許沒有任何索引和主鍵的表存在,MyISAM的索引都是保存行的地址。
InnoDB引擎若是沒有設定主鍵或者非空惟一索引,就會自動生成一個6字節的主鍵(用戶不可見),InnoDB的數據是主索引的一部分,附加索引保存的是主索引的值。
MyISAM保存有表的總行數,若是select count(*) from table;會直接取出出該值。
InnoDB沒有保存表的總行數,若是使用select count(*) from table;就會遍歷整個表,消耗至關大,可是在加了wehre 條件後,MyISAM和InnoDB處理的方式都同樣。
MyISAM支持 FULLTEXT類型的全文索引。
InnoDB不支持FULLTEXT類型的全文索引,可是InnoDB可使用sphinx插件支持全文索引,而且效果更好。(sphinx 是一個開源軟件,提供多種語言的API接口,能夠優化mysql的各類查詢)。
使用這條命令時,InnoDB不會重新創建表,而是一條一條的刪除數據,在InnoDB上若是要清空保存有大量數據的表,最好不要使用這個命令。(推薦使用truncate table,不過須要用戶有drop此表的權限)。
MyISAM的索引以表名+.MYI文件分別保存。
InnoDB的索引和數據一塊兒保存在表空間裏。
能夠用 show create table tablename 命令看錶的引擎類型。
對不支持事務的表作start/commit操做沒有任何效果,在執行commit前已經提交。
能夠執行如下命令來切換非事務表到事務(數據不會丟失),InnoDB表比MyISAM表更安全:alter table tablename type=innodb;或者使用 alter table tablename engine = innodb;
默認innodb是開啓自動提交的,若是你按照MyISAM的使用方法來編寫代碼頁不會存在錯誤,只是性能會很低。如何在編寫代碼時候提升數據庫性能呢?
1> 儘可能將多個語句綁到一個事務中,進行提交,避免屢次提交致使的數據庫開銷。
2> 在一個事務得到排他鎖或者意向排他鎖之後,若是後面還有須要處理的sql語句,在這兩條或者多條sql語句之間程序應儘可能少的進行邏輯運算和處理,減小鎖的時間。
3> 儘可能避免死鎖。
4> sql語句若是有where子句必定要使用索引,儘可能避免獲取意向排他鎖。
5> 針對開發,通常日誌表之類的都是不修改的,能夠用MyISAM,而其餘表要用到事務,要頻繁修改的能夠用InnoDB。