事務是邏輯上的一組操作,要麼都執行,要麼都不執行。
事務最經典也經常被拿出來說例子就是轉賬了。假如小明要給小紅轉賬1000元,這個轉賬會涉及到兩個關鍵操作就是:將小明的餘額減少1000元,將小紅的餘額增加1000元。萬一在這兩個操作之間突然出現錯誤比如銀行系統崩潰,導致小明餘額減少而小紅的餘額沒有增加,這樣就不對了。事務就是保證這兩個關鍵操作要麼都成功,要麼都要失敗。
原子性: 事務是最小的執行單位,不允許分割。事務的原子性確保動作要麼全部完成,要麼完全不起作用;
一致性: 執行事務前後,資料保持一致,多個事務對同乙個資料讀取的結果是相同的;
隔離性: 併發訪問資料庫時,乙個使用者的事務不被其他事務所干擾,各併發事務之間資料庫是獨立的;
永續性: 乙個事務被提交之後。它對資料庫中資料的改變是持久的,即使資料庫發生故障也不應該對其有任何影響。
在典型的應用程式中,多個事務併發執行,經常會操作相同的資料來完成各自的任務(多個使用者對統一資料進行操作)。併發雖然是必須的,但可能會導致以下的問題。
髒讀(dirty read):當乙個事務正在訪問資料並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時另外乙個事務也訪問了這個資料,然後使用了這個資料。因為這個資料是還沒有提交的資料,那麼另外乙個事務讀到的這個資料是「髒資料」,依據「髒資料」所做的操作可能是不正確的。解決辦法:把資料庫的事務隔離級別調整到read_committed(讀取已提交)
丟失修改(lost to modify):指在乙個事務讀取乙個資料時,另外乙個事務也訪問了該資料,那麼在第乙個事務中修改了這個資料後,第二個事務也修改了這個資料。這樣第乙個事務內的修改結果就被丟失,因此稱為丟失修改。 例如:事務1讀取某錶中的資料a=20,事務2也讀取a=20,事務1修改a=a-1,事務2也修改a=a-1,最終結果a=19,事務1的修改被丟失。
不可重複讀(unrepeatableread):指在乙個事務內多次讀同一資料。在這個事務還沒有結束時,另乙個事務也訪問該資料。那麼,在第乙個事務中的兩次讀資料之間,由於第二個事務的修改導致第乙個事務兩次讀取的資料可能不太一樣。這就發生了在乙個事務內兩次讀到的資料是不一樣的情況,因此稱為不可重複讀。
不可重複讀例子
在事務1中,mary 讀取了自己的工資為1000,操作並沒有完成在乙個事務中前後兩次讀取的結果並不致,導致了不可重複讀。begin transaction;
select salary from employeewhere id =maryid;
在事務2中,這時財務人員修改了mary的工資為2000,並提交了事務.
begin transaction;
update employeeset salary = 2000where id =maryid;
commit;
在事務1中,mary 再次讀取自己的工資時,工資變為了2000
select salary from employeewhere id = maryid;
解決辦法:把資料庫的事務隔離級別調整到repeatable_read(可重複讀)
幻讀(phantom read):幻讀與不可重複讀類似。它發生在乙個事務(t1)讀取了幾行資料,接著另乙個併發事務(t2)插入了一些資料時。在隨後的查詢中,第乙個事務(t1)就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。
解決辦法:把資料庫的事務隔離級別調整到serializable_read(可序列化)
不可重複度和幻讀區別:
不可重複讀的重點是修改比如多次讀取一條記錄發現其中某些列的值被修改,幻讀的重點在於新增或者刪除比如多次讀取一條記錄發現記錄增多或減少了。
事務隔離級別有哪些?mysql的預設隔離級別是?
sql 標準定義了四個隔離級別:
read-uncommitted(讀取未提交):最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀。
read-committed(讀取已提交):允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生。
repeatable-read(可重複讀):對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生。
serializable(可序列化):最高的隔離級別,完全服從acid的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。
mysql innodb 儲存引擎的預設支援的隔離級別是 repeatable-read(可重讀)。我們可以通過select @@tx_isolation;命令來檢視
這裡需要注意的是:與 sql 標準不同的地方在於innodb 儲存引擎在 repeatable-read(可重讀)事務隔離級別下使用的是next-key lock 鎖演算法,因此可以避免幻讀的產生,這與其他資料庫系統(如 sql server)是不同的。所以說innodb 儲存引擎的預設支援的隔離級別是 repeatable-read(可重讀) 已經可以完全保證事務的隔離性要求,即達到了 sql標準的serializable(可序列化)隔離級別。
因為隔離級別越低,事務請求的鎖越少,所以大部分資料庫系統的隔離級別都是read-committed(讀取提交內容):,但是你要知道的是innodb 儲存引擎預設使用 repeatable-read(可重讀)並不會有任何效能損失。
innodb 儲存引擎在 分布式事務 的情況下一般會用到serializable(可序列化)隔離級別。
鎖機制與innodb鎖演算法
myisam和innodb儲存引擎使用的鎖:
myisam採用表級鎖(table-level locking)。
innodb支援行級鎖(row-level locking)和表級鎖,預設為行級鎖
表級鎖和行級鎖對比:
innodb儲存引擎的鎖的演算法有三種:
最後說一下
myisam
和innodb
區別myisam是mysql的預設資料庫引擎(5.5版之前)。雖然效能極佳,而且提供了大量的特性,包括全文索引、壓縮、空間函式等,但myisam不支援事務和行級鎖,而且最大的缺陷就是崩潰後無法安全恢復。不過,5.5版本之後,mysql引入了innodb(事務性資料庫引擎),mysql 5.5版本後預設的儲存引擎為innodb。
大多數時候我們使用的都是 innodb 儲存引擎,但是在某些情況下使用 myisam 也是合適的比如讀密集的情況下。(如果你不介意 myisam 崩潰回覆問題的話)。
兩者的對比:
是否支援行級鎖: myisam 只有表級鎖(table-level locking),而innodb 支援行級鎖(row-level locking)和表級鎖,預設為行級鎖。
是否支援事務和崩潰後的安全恢復: myisam強調的是效能,每次查詢具有原子性,其執行數度比innodb型別更快,但是不提供事務支援。但是innodb提供事務支援事務,外部鍵等高階資料庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (acid compliant))型表。
是否支援外來鍵:myisam不支援,而innodb支援。
是否支援mvcc:僅 innodb 支援。應對高併發事務, mvcc比單純的加鎖更高效;mvcc只在read committed
和repeatable read
兩個隔離級別下工作;mvcc可以使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現;各資料庫中mvcc實現並不統一。推薦閱讀:mysql-innodb-mvcc多版本併發控制
事務 相關知識點
1.關閉自動提交功能。2.演示事務 裡面的事務,主要是針對連線來的。1.通過 x.setautocommit false 來關閉自動提交的設定。2.提交事務 x.commit 3.回滾事務 x.rollback test public void testtransaction catch sqlex...
事務相關知識點
原子性 atomicity 事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗。一致性 consistency 事務執行後,資料庫狀態與其它業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的。隔離性 isolation 隔離...
話說事務相關知識
1.1 事務的四大特性cuid 事務 transaction 是併發控制的單位,是使用者定義的乙個操作序列。這些操作要麼都做,要麼都不做,是乙個不可分割的工作單位。通過事務,sql server能將邏輯相關的一組操作繫結在一起,以便伺服器保持資料的完整性。事務通常是以begin transactio...