什么是事務
數(shù)據(jù)庫的事務(Transaction)是一種機制、一個操作序列,包含了一組數(shù)據(jù)庫操作命令。事務把所有的命令作為一個整體一起向系統(tǒng)
提交或撤銷操作請求,即這一組數(shù)據(jù)庫命令要么都執(zhí)行,要么都不執(zhí)行,因此事務是一個不可分割的工作邏輯單元。
在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時,事務是作為最小的控制單元來使用的,特別適用于多用戶同時操作的數(shù)據(jù)庫系統(tǒng)。例如,航空公司的訂票系統(tǒng)、銀行、保險公司以及證券交易系統(tǒng)等。
事務的特性(ACID)
① 原子性:事務是最小的執(zhí)行單位,不允許分割。事務的原子性確保動作要么全部完成,要么完全不起作用;
例如轉(zhuǎn)賬的這兩個關鍵操作(將張三的余額減少200元,將李四的余額增加200元)。要么全部完成,要么全部失敗。
② 一致性: 確保從一個正確的狀態(tài)轉(zhuǎn)換到另外一個正確的狀態(tài),這就是一致性。例如轉(zhuǎn)賬業(yè)務中,將張三的余額減少200元,中間發(fā)生斷電情況,
李四的余額沒有增加200元,這個就是不正確的狀態(tài),違反一致性。又比如表更新事務,一部分數(shù)據(jù)更新了,但一部分數(shù)據(jù)沒有更新,這也是違反一致性的;
③ 隔離性:并發(fā)訪問數(shù)據(jù)庫時,一個用戶的事務不被其他事務所干擾,各并發(fā)事務之間數(shù)據(jù)庫是獨立的;
④ 持久性:一個事務被提交之后,對數(shù)據(jù)庫中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫發(fā)生故障也不應該對其有任何影響。
數(shù)據(jù)庫隔離級別及原理
Read Uncommitted(讀未提交)
Read Committed(讀已提交)
Repeatable Read(可重復讀)
Serializable(可序列化)
鎖類型簡述
共享鎖(S鎖):假設事務T1對數(shù)據(jù)A加上共享鎖,那么事務T2可以讀數(shù)據(jù)A,不能修改數(shù)據(jù)A。
排他鎖(X鎖):假設事務T1對數(shù)據(jù)A加上排他鎖,那么事務T2不能讀數(shù)據(jù)A,不能修改數(shù)據(jù)A。
各個隔離級別鎖應用
讀未提交
Read Uncommitted:最低隔離級別,什么都不要做,一個事務可以讀到另一個事務未提交的結(jié)果。所有的并發(fā)事務問題都會發(fā)生。
原理:
事務對當前讀取的數(shù)據(jù)不加鎖;
事務對數(shù)據(jù)更新前添加 行級共享鎖,直到事務結(jié)束才釋放。
可能發(fā)生的情況:
事務1讀取某些數(shù)據(jù)記錄時,事務2也能對這些記錄進行讀取、更新;當事務2對這些記錄進行更新時,事務1再次讀取記錄,能讀到事務2對該記錄的修改版本,即使更新尚未提交。
事務1更新某些數(shù)據(jù)記錄時,事務2不能對這行記錄做更新,直到事務1結(jié)束。
簡單地理解就是:
允許事務同時讀數(shù)據(jù)
允許一個事務讀取數(shù)據(jù)同時另外一個事務修改數(shù)據(jù)
必須等更新數(shù)據(jù)的事務執(zhí)行完成后,才能對執(zhí)行其他的讀取或者修改該數(shù)據(jù)的事務
讀已提交
Read Committed:只有在事務提交后,其更新結(jié)果才會被其他事務看見??梢越鉀Q臟讀問題。
原理:
事務對當前被讀取的數(shù)據(jù)加 行級共享鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共享鎖;
事務在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對其加 行級排他鎖,直到事務結(jié)束才釋放。
可能發(fā)生的情況:
事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的只能是事務2對其更新前的版本,要不就是事務2提交后的版本。
事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結(jié)束。
簡單地理解就是:
允許事務同時讀數(shù)據(jù)
必須一個事務讀取完數(shù)據(jù)后,另外一個事務才能修改該數(shù)據(jù)
必須等更新數(shù)據(jù)的事務執(zhí)行完成后,才能對執(zhí)行其他的讀取或者修改該數(shù)據(jù)的事務
可重復讀
Repeated Read:在一個事務中,對于同一份數(shù)據(jù)的讀取結(jié)果總是相同的,無論是否有其他事務對這份數(shù)據(jù)進行操作,以及這個事務是否提交??梢越鉀Q臟讀、不可重復讀。
原理:
事務在讀取某數(shù)據(jù)的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結(jié)束才釋放;
事務在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對其加 行級排他鎖,直到事務結(jié)束才釋放。
可能發(fā)生的情況:
事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的仍然是第一次讀取的那個版本。
事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結(jié)束。
簡單地理解就是:
允許事務同時讀數(shù)據(jù)
必須等讀取數(shù)據(jù)的事務執(zhí)行完成后,才能對執(zhí)行其他的修改該數(shù)據(jù)的事務
必須等更新數(shù)據(jù)的事務執(zhí)行完成后,才能對執(zhí)行其他的讀取或者修改該數(shù)據(jù)的事務
可序列化
Serialization:事務串行化執(zhí)行,隔離級別最高,犧牲了系統(tǒng)的并發(fā)性。可以解決并發(fā)事務的所有問題。
事務在讀取某數(shù)據(jù)的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結(jié)束才釋放;
事務在更新某數(shù)據(jù)的瞬間(就是發(fā)生更新的瞬間),必須先對其加 行級排他鎖,直到事務結(jié)束才釋放。
可能發(fā)生的情況:
事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的仍然是第一次讀取的那個版本。
事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結(jié)束。
簡單地理解就是:
所有的事務必須等上一個事務執(zhí)行完成后才開始執(zhí)行
MySQL 存儲引擎 MyISAM 與 InnoDB 兩種存儲引擎的區(qū)別
一、InnoDB支持事務,MyISAM不支持,這一點是非常之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪個出錯還可以回滾還原,而MyISAM就不可以了。
二、MyISAM適合查詢以及插入為主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用
三、InnoDB支持外鍵,MyISAM不支持
四、MySQL 在 5.1 之前版本默認存儲引擎是 MyISAM,5.1 之后版本默認存儲引擎是 InnoDB
五、InnoDB不支持FULLTEXT類型的索引
六、InnoDB中不保存表的行數(shù),如select count(*) from table時,InnoDB需要掃描一遍整個表來計算有多少行,但是MyISAM只要簡
單的讀出保存好的行數(shù)即可。注意的是,當count(*)語句包含where條件時MyISAM也需要掃描整個表
七、對于自增長的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中可以和其他字段一起建立聯(lián)合索引
八、清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MyISAM則會重建表
九、InnoDB支持行鎖(某些情況下還是鎖整表,如 update table set a=1 where user like ‘%lee%’
通過以上九點區(qū)別,結(jié)合個人博客的特點,推薦個人博客系統(tǒng)使用MyISAM,因為在博客里主要操作是讀取和寫入,很少有鏈式操
作。所以選擇MyISAM引擎使你博客打開頁面的效率要高于InnoDB引擎的博客,當然只是個人的建議,大多數(shù)博客還是根據(jù)實際情
況下謹慎選擇。
一些關于MyISAM與InnoDB選擇使用:
MYISAM和INNODB是Mysql數(shù)據(jù)庫提供的兩種存儲引擎。兩者的優(yōu)劣可謂是各有千秋。INNODB會支持一些關系數(shù)據(jù)庫的高級功
能,如事務功能和行級鎖,MYISAM不支持。MYISAM的性能更優(yōu),占用的存儲空間少。所以,選擇何種存儲引擎,視具體應用而
定。
如果你的應用程序一定要使用事務,毫無疑問你要選擇INNODB引擎。但要注意,INNODB的行級鎖是有條件的。在where條件沒有使用主鍵時,照樣會鎖全表。
比如DELETE FROM mytable這樣的刪除語句。如果你的應用程序?qū)Σ樵冃阅芤筝^高,就要使用MYISAM了。MYISAM索引和數(shù)據(jù)是分開的,而且其索引是壓縮的,可以更好地利用內(nèi)存。
所以它的查詢性能明顯優(yōu)于INNODB。
壓縮后的索引也能節(jié)約一些磁盤空間。MYISAM擁有全文索引的功能,這可以極大地優(yōu)化LIKE查詢的效率。
有人說MYISAM只能用于小型應用,其實這只是一種偏見。如果數(shù)據(jù)量比較大,這是需要通過升級架構(gòu)來解決,比如分表分庫,而不是單純地依賴存儲引擎。
關于Mysql數(shù)據(jù)庫默認的存儲引擎:
MyISAM和InnoDB是MySQL的兩種存儲引擎。
如果是默認安裝,那就應該是InnoDB,你可以在my.ini文件中找到default-storage-engine=INNODB;當然你可以在建表時指定相應的存儲引擎。
通過show create table xx 可以看見相應信息。
Mysql中InnoDB和MyISAM的比較
MyISAM:
每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數(shù)據(jù)文件的擴展名為.MYD (MYData)。
MyISAM表格可以被壓縮,而且它們支持全文搜索。不支持事務,而且也不支持外鍵。如果事物回滾將造成不完全回滾,不具有原子
性。在進行update時進行表鎖,并發(fā)量相對較小。如果執(zhí)行大量的SELECT,MyISAM是更好的選擇。
MyISAM的索引和數(shù)據(jù)是分開的,并且索引是有壓縮的,內(nèi)存使用率就對應提高了不少。能加載更多索引,而Innodb是索引和數(shù)據(jù)是
緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小
MyISAM緩存在內(nèi)存的是索引,不是數(shù)據(jù)。而InnoDB緩存在內(nèi)存的是數(shù)據(jù),相對來說,服務器內(nèi)存越大,InnoDB發(fā)揮的優(yōu)勢越大。
優(yōu)點:查詢數(shù)據(jù)相對較快,適合大量的select,可以全文索引。
缺點:不支持事務,不支持外鍵,并發(fā)量較小,不適合大量update
InnoDB:
這種類型是事務安全的。.它與BDB類型具有相同的特性,它們還支持外鍵。InnoDB表格速度很快。具有比BDB還豐富的特性,因此如果
需要一個事務安全的存儲引擎,建議使用它。在update時表進行行鎖,并發(fā)量相對較大。
如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE,出于性能方面的考慮,應該使用InnoDB表。
優(yōu)點:支持事務,支持外鍵,并發(fā)量較大,適合大量update
缺點:查詢數(shù)據(jù)相對較快,不適合大量的select
對于支持事物的InnoDB類型的表,影響速度的主要原因是AUTOCOMMIT默認設置是打開的,而且程序沒有顯式調(diào)用BEGIN 開始事
務,導致每插入一條都自動Commit,嚴重影響了速度??梢栽趫?zhí)行sql前調(diào)用begin,多條sql形成一個事物(即使autocommit打開也可以),將大大提高性能。
基本的差別為:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持。
MyISAM類型的表強調(diào)的是性能,其執(zhí)行數(shù)度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持以及外部鍵等高級數(shù)據(jù)庫功能。
innodb和myisam更新比較:
innodb的數(shù)據(jù)組織就是按照主鍵建成的一個B+樹,如果沒有顯示的定義主鍵,那么innodb會選一個not null unique key,作為主鍵,如果還是沒有,
那么innodb會創(chuàng)建一個 6字節(jié)的主鍵,主鍵索引到
頁不是具體行位置。不是遞增的主鍵會使得插入的速度很慢,例如使用手機號或身份證號做為主鍵,所以善用AUTO_INCREMENT。
插入的速度和查詢的速度有時候是不可調(diào)和的矛盾
說InnoDB不適合做count是不對的,MyISAM也是一樣的慢,只不過MyISAM將正表的行數(shù)緩存起來,所以count整表很快,如果有查
詢條件,并且不是主鍵查詢,那就沒有什么區(qū)別,主鍵count慢的原因是innodb是按照主鍵組織的,按照主鍵count的時候,會加載數(shù)據(jù)
InnoDB的頁式存儲會使得InnoDB更容易做整表緩存和熱備份,如果表索引很多,那么InnoDB的更新速度要大于MyISAM,因為InnoDB的輔助索引關聯(lián)的是表的主鍵,
是一個邏輯的值,而MyISAM的所有索引關聯(lián)的是數(shù)據(jù)的物理位置,更新時有可能數(shù)據(jù)的物理位置發(fā)生變化,如果發(fā)生變化,那么所有的索引都要做更新
InnoDB 中不保存表的具體行數(shù),也就是說,執(zhí)行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyI
SAM只要簡單的讀出保存好的行數(shù)即可。注意的是,當count(*)語句包含 where條件時,兩種表的操作是一樣的。