1. 程式人生 > >事務學習筆記

事務學習筆記

ron nlog 失敗 art rom lsp 自動提交 隱患 into

事務是一組訪問並可能更新數據庫內容的SQL組成的執行單元,是數據庫並發控制和事務回滾的基本單位。 一個事務可能包含多個SQL,要麽都失敗,要麽都成功。 事務具備4個基本屬性 Atomic,同一個事務裏,要麽都提交,要麽都回滾。 Consistency,即在事務開始之前和事務結束之後,數據庫的完整性約束沒有被破壞。 Isolation,並發事務間的數據時彼此隔離的。 Durablliy,事務提交後,所有的結果務必被持久化。 支持事務的引擎:InnoDB、NDBCluster、TokuDB。

不支持事務的引擎:MyISAM、MEMORY/HEAP

查看某個引擎是否支持事務:show engines\G;

顯示開啟事務: START TRANSACTION [READ WRITE] -- 默認 [WITH CONSISTENT SNAPSHOT] --發起一個一致性快照讀,當前時刻提交的數據,都應該備份出來,從此刻起到之後的數據都不應該看得到。 [READ ONLYO] 或者BEGIN 開啟/關閉自動提交 set autocommit | @@autocimmit =0|1

提交事務:

顯式提交:commit

隱試提交:

BEGIN

START TRANSACTION

SET AUTOCOMMIT=1 / 其他非事務語句(DDL/DCL)。

回滾事務 顯示回滾:ROLLBACK。 隱式回滾:連接端口/超時。 autocommit=0 必要嗎? 好處:多語句提交時,不會每個SQL單獨提交,提高TPS 麻煩:有個事務忘記提交,鎖一直未釋放;另一個事務長期鎖等待,嚴重影響TPS。 如果沒有事務控制的話,那麽並發讀寫數據庫會有什麽隱患? 臟讀:一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務更新後達到了滿足其查詢條件的舊數據(此時它還未被提交),這種現象就稱為“臟讀”。 不可重復讀:一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務更新後達到了滿足其查詢條件的舊數據(此時它已被提交),這種現象就稱為“不可重復讀”。 幻讀:一個事務按相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的新數據(此時它已被提交),這種現象就被稱為“幻讀”。 事務隔離級別 Read Uncommitted(讀未提交)隔離級別最低 允許臟讀,允許事務查看其它事務所進行的未提交更改。 Read Commited(讀已提交) 允許幻讀,允許事務查看其它事務所進行的已提交更改。 Repeatable Read(可重復讀) 消除了臟讀、不可重復讀、幻讀,保證事務一致性。 確保每個事務的讀取結構都是一樣的,默認隔離級別。 Serializable(串行)隔離級別最高 串行化讀,每次讀都需要獲得表級共享鎖,讀寫間相互都會阻塞。 相當於MyISAM引擎,不支持並發了。
隔離級別 臟讀 不可重復讀 幻讀
Read Uncommitted(讀未提交) 可能 可能 可能
Read Commited(讀已提交) 不可能 可能 可能
Repeatable read(可重復讀) 不可能 不可能 不可能(InnoDB特定條件下可能)
Serializable(串行) 不可能 不可能 不可能

my.cnf配置 [mysqld]分段中,加入一行 transaction-isolation="READ-COMMITTED" #默認值是REPEATABLE-READ 在線(全局)修改 SET [GLOBAL] TRANSACTION ISOLATION LEVEL READ COMMITTED 查看事務隔離級別 select @@tx_isolation; 或者 show variables like ‘%iso%‘; 查看當前隔離級別 SELECT @@GLOBAL.TX_ISOLATION,@@SESSION.TX_ISOLATION; 例子: create table t1( c1 int(11) not null, c2 int(11) default null, c3 int(11) default null, primary key(c1), key c2(c2) ) +------+-------------+ | c1 | c2 | c3 | +------+-------------+ | 0 | 0 | 0 | | 1 | 1 | 1 | | 2 | 2 | 2 | | 3 | 3 | 3 | +------+------+------+
讀未提交,Read uncommitted,RU隔離級別
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
update t1 set c3=30 where c2=2
select * from t1 where c2=2
| 2 | 2 | 30 |
讀到了t1還未提交的數據
讀已提交,Read committed,RC隔離級別
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
update t1 set c3=30 where c2=2
select * from t1 where c2=2
| 2 | 2 | 2 |
t1未提交時,還是讀取到舊數據
select * from t1 where c2=2 for update
希望讀取到最新版本,被阻塞,需等待
commit
select * from t1 where c2=2
| 2 | 2 | 30 |
t1提交後,讀取到新數據
RC下的幻讀
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
insert into t1select 4,2,2
select * from t1 where c2=2
| 2 | 2 | 2 |
t1未提交時,還是讀取到舊數據
select * from t1 where c2=2 for update
行鎖等待
commit
select * from t1 where c2=2
| 2 | 2 | 2 |
| 4 | 2 | 2 | ==>幻讀
t1提交後,是否加了for update都可以讀取到新數據
可重復讀,Repeatable read,RR隔離級別
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL RPEATABLE READ
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
update t1 set c3=30 where c2=2;
commit;
select * from t1 where c2=2
| 2 | 2 | 2 |

select * from t1 where c2=2 for update
| 2 | 2 | 30 |
select * from t1 where c2=2
| 2 | 2 | 2 |
RR隔離級別可以避免幻讀
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL RPEATABLE READ
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
insert into t1select 4,2,2
ERROR 1250(HY000):Lock wait timeout exceeded;try restarting transaction
鎖住c2=2這個gap,不允許有新的寫入
串行,serializable
session1 session2
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin begin
select * from t1 where c2=2
| 2 | 2 | 2 |
select * from t1 where c2=2
| 2 | 2 | 2 |
update t1 set c3=20 where c2=20
ERROR 1250(HY000):Lock wait timeout exceeded;try restarting transaction
InnoDB如何解決幻讀的 1.RR級別下解決了幻讀問題。 2.引入gap lock,把兩條記錄中間的gap鎖住,避免其他事務寫入。 3.存在幻讀的條件:(1)<=RC級別。(2)或RR+ innodb_locks_unsafe_for_binlog=1

事務學習筆記