天天看點

mysql 開啟事務_什麼是事務

事務:

事務指的是邏輯上的一組操作,組成這組操作的各個單元要麼全都成功,要麼全都失敗。

作用:保證在一個事務中多次操作資料庫表中資料時,要麼全部成功,要麼全部失敗。

事務的特性(ACID)

資料庫的事務必須具備ACID特性,ACID是指 Atomic(原子性)、Consistensy(一緻性)、Isolation(隔離型)和Durability(持久性)的英文縮寫。

1、原子性(Atomicity)

事務包裝的一組sql,要麼都執行成功,要麼都失敗。這些操作是不可分割的。

2、一緻性(Consistency)

資料庫的資料狀态是一緻的。

事務的成功與失敗,最終資料庫的資料都是符合實際生活的業務邏輯。一緻性絕大多數依賴業務邏輯和原子性。

3、持久性:(Durability)

事務成功送出之後,對于資料庫的改變是永久的。哪怕資料庫發生異常,重新開機之後資料亦然存在。

4、隔離性(Isolation)

一個事務的成功或者失敗對于其他的事務是沒有影響。2個事務應該互相獨立。

事務問題:

髒讀:讀正在編輯中的資料(不能容忍)

髒資料(正在編輯中的資料) dirty data

Clean data : 編輯完成的資料(儲存,撤銷)

幻讀(虛讀):事務A首先根據條件索引得到N條資料,然後事務B改變了這N條資料之外的M條或者增添了M條符合事務A搜尋條件的資料,導緻事務A再次搜尋發現有N+M條資料了,就産生了幻讀。

也就是說,目前事務讀第一次取到的資料比後來讀取到資料條目少。

不可重複讀:同一事務中,前後多次讀到的資料不一樣

在金融/銀行類機構,這個問題一定要解決

幻讀與不可重複讀的差別:

兩者有些相似,但是前者針對的是insert,後者針對的update或delete。

spring(資料庫)事務隔離級别分為四種(級别遞減):

1、Serializable (串行化):最嚴格的級别,事務串行執行,資源消耗最大;

2、REPEATABLE READ(重複讀) :保證了一個事務不會修改已經由另一個事務讀取但未送出(復原)的資料。避免了“髒讀取”和“不可重複讀取”的情況,但不能避免“幻讀”,但是帶來了更多的性能損失。

3、READ COMMITTED (送出讀):大多數主流資料庫的預設事務等級,保證了一個事務不會讀到另一個并行事務已修改但未送出的資料,避免了“髒讀取”,但不能避免“幻讀”和“不可重複讀取”。該級别适用于大多數系統。

4、Read Uncommitted(未送出讀) :事務中的修改,即使沒有送出,其他事務也可以看得到,會導緻“髒讀”、“幻讀”和“不可重複讀取”。

隔離級别與解決問題

資料庫規範規定了4種隔離級别,分别用于描述兩個事務并發的所有情況。

read uncommitted 讀未送出,一個事務讀到另一個事務沒有送出的資料。

a)存在:3個問題(髒讀、不可重複讀、虛讀)。

b)解決:0個問題

read committed 讀已送出,一個事務讀到另一個事務已經送出的資料。

a)存在:2個問題(不可重複讀、虛讀)。

b)解決:1個問題(髒讀)

repeatable read(): 可重複讀,在一個事務中讀到的資料始終保持一緻,無論另一個事務是否送出。

a)存在:1個問題(虛讀)。

b)解決:2個問題(髒讀、不可重複讀)

serializable 串行化,同時隻能執行一個事務,相當于事務中的單線程。

a)存在:0個問題。

b)解決:3個問題(髒讀、不可重複讀、虛讀)

安全和性能對比

安全性:serializable > repeatable read > read committed > read uncommitted

性能 : serializable < repeatable read < read committed < read uncommitted

常見資料庫的預設隔離級别:

MySql:repeatable read

Oracle:read committed

事務在解決生活中的問題時,邏輯是這樣的:

mysql 開啟事務_什麼是事務

MySQL事務操作

sql語句——描述

start transaction;——開啟事務 (禁止了自動送出)

commit;——送出事務 (手動)

rollback;——復原事務

準備資料:

mysql 開啟事務_什麼是事務

操作:MySQL中可以有兩種方式進行事務管理

  • 手動送出:先開啟,再送出
  • 自動送出:MySQL預設自動送出。即執行一條sql語句送出一次事務。

方式一、手動

mysql 開啟事務_什麼是事務
mysql 開啟事務_什麼是事務

(事務送出之後,sql語句對資料庫産生的操作才會被永久的儲存)

事務是如何處理異常的?

a=1000 b=1000

開啟事務(start transaction;)

update t_account set money = money -100 where name=‘a’; a=900

出現異常

update t_account set money = money +100 where name=‘b’;

事務的復原(rollback;)(撤銷已經成功執行的sql語句,回到開啟事務之前的狀态)

a=1000 b=1000;

注意:隻要送出事務,那麼資料就會長久儲存了,就不能復原事務了。即送出或者復原事務都是代表結束目前事務的操作。

方式二、自動送出,通過修改mysql全局變量“autocommit”進行控制。

通過以下指令可以檢視目前autocommit模式:

show variables like ‘%commit%’;

mysql 開啟事務_什麼是事務

設定自動送出的參數為OFF

set autocommit = 0; – 0:OFF 1:ON

說明:

1)MySql預設自動送出。即執行一條sql語句送出一次事務。

2)設定autocommit為off狀态,隻是臨時性的,下次重新啟動mysql,autocommit依然變為on狀态。

3)如果設定autocommit為off狀态,那麼當我們執行一條sql語句,就不會自動送出事務,重新啟動可視化工具,資料并沒有改變。

4)如果設定autocommit為on狀态,如果我們先執行 start transaction; 然後在執行修改資料庫的語句:

update account set money = money-100 where name=‘a’;

update account set money = money+100 where name=‘b’;

那麼此時就表示上述修改資料庫的sql語句都在同一個事務中,此時必須手動送出事務,即commit;

換句話說,如果我們手動開啟事務 start transaction; 那麼此時mysql就不會自動送出事務,必須手動送出事務。

5)如果設定autocommit為on狀态,如果我們不執行 start transaction; 直接執行修改資料庫的語句:

update account set money = money-100 where name=‘a’;

update account set money = money+100 where name=‘b’;

那麼此時mysql就會自動送出事務。即上述每條sql語句就是一個事務。

JDBC事務操作

mysql 開啟事務_什麼是事務

Connection對象的方法名——描述

conn.setAutoCommit(false)——開啟事務(禁止自動送出)

conn.commit()——送出事務

conn.rollback()——復原事務

注意:在jdbc事務操作中,事務的控制都是通過Connection對象完成的,當一個完整的業務操作前,我們首先使用conn.setAutoCommit(false)來開啟事務。預設情況下是true的,表示關閉事務,那麼一條sql語句就是一個事務,預設送出事務。如果設定為false,那麼表示開啟事務,所有的sql語句就會都在一個事務中。

當業務操作完成之後,如果整個操作沒有問題,我們需要使用conn.commit()來送出事務。當然了,如果出現了異常,我們需要使用conn.rollback()撤銷所有的操作,是以出現異常,需要進行事務的復原。

常見事務問題之詳解

髒讀:隻一個事務讀取了另外一個事務未送出的資料

set session transaction isolation level read uncommitted;

mysql 開啟事務_什麼是事務

不可重複讀:在一個事務内多次讀取表中資料,多次讀取的結果不同。(和髒讀的差別:不可重複讀是讀取已送出的資料)

set session transaction isolation level read committed;

mysql 開啟事務_什麼是事務

幻讀(虛讀):

set session transaction isolation level repeatable read;

mysql 開啟事務_什麼是事務

指在一個事務中 讀取 另一個事務 插入或删除 資料記錄,導緻目前事務 讀取資料前後不一緻。

存款100元但未送出,這時銀行做報表 統計總額為500元,丙将事務送出,銀行再統計就變成了 600元,兩次統計結果不一緻,銀行便會不知所措。

一個事務 讀取 另一個事務 已經送出的資料,強調的是 記錄數 的變化,常有sql類型為 insert和 delete。

注意: 在mysql資料庫中,底層對于幻讀做了優化,示範不了。

serializable串行化

可以避免所有的問題。資料庫執行這個事務,其他事務必須等待目前事務執行完畢,才能被執行。

串行為什麼可以解決所有問題?因為上述問題都是由并行執行引起的,是以改成所有事務一次執行(串行),就可以解決所有問題。

繼續閱讀