ACDI事物的四大特性
- 原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
比如:轉賬轉過去的加和轉時候的減必須一次發生 - 一致性(Consistency)
事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。
比如:轉賬時雙方的總數在轉賬的時候保持一致 - 隔離性(Isolation)
事務的隔離性是多個用戶併發訪問數據庫時,數據庫爲每一個用戶開啓的事務,不能被其他事務的操作數據所幹擾,多個併發事務之間要相互隔離。
比如:多個用戶操縱,防止數據干擾,就要爲每個客戶開啓一個自己的事務; - 持久性(Durability)
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響。
比如:如果我commit提交後 無論發生什麼都 都不會影響到我提交的數據;
數據庫開啓事務命令
- start transaction 開啓事務
- Rollback 回滾事務
- Commit 提交事務
當Jdbc程序向數據庫獲得一個Connection對象時,默認情況下這個Connection對象會自動向數據庫提交在它上面發送的SQL語句。若想關閉這種默認提交方式,讓多條SQL在一個事務中執行,可使用下列語句:
JDBC控制事務語句
Connection.setAutoCommit(false);如同數據庫開啓命令的 start transaction
Connection.rollback(); == rollback
Connection.commit(); == commit
設置事務回滾點
Savepoint sp = conn.setSavepoint();
Conn.rollback(sp);
Conn.commit(); //回滾後必須要提交
數據庫共定義了四種隔離級別:
Serializable:可避免髒讀、不可重複讀、虛讀情況的發生。(串行化)
Repeatable read:可避免髒讀、不可重複讀情況的發生。(可重複讀)
Read committed:可避免髒讀情況發生(讀已提交)。
Read uncommitted:最低級別,以上情況均無法保證。(讀未提交)
set transaction isolation level 設置事務隔離級別
select @@tx_isolation 查詢當前事務隔離級別
演示不同隔離級別下的併發問題
1.當把事務的隔離級別設置爲read uncommitted時,會引發髒讀、不可重複讀和虛讀
A窗口
set transaction isolation level read uncommitted;
start transaction;
select * from account;
-----發現a帳戶是1000元,轉到b窗口
select * from account
-----發現a多了100元,這時候a讀到了b未提交的數據(髒讀)
B窗口
start transaction;
update account set money=money+100 where name='aaa';
-----不要提交,轉到a窗口查詢
2.當把事務的隔離級別設置爲read committed時,會引發不可重複讀和虛讀,但避免了髒讀
A窗口
set transaction isolation level read committed;
start transaction;
select * from account;
-----發現a帳戶是1000元,轉到b窗口
select * from account;
-----發現a帳戶多了100,這時候,a讀到了別的事務提交的數據,兩次讀取a帳戶讀到的是不同的結果(不可重複讀)
B窗口
start transaction;
update account set money=money+100 where name='aaa';
commit;
-----轉到a窗口
3.當把事務的隔離級別設置爲repeatable read(mysql默認級別)時,會引發虛讀,但避免了髒讀、不可重複讀
A窗口
set transaction isolation level repeatable read;
start transaction;
select * from account;
----發現表有4個記錄,轉到b窗口
select * from account;
----可能發現表有5條記如,這時候發生了a讀取到另外一個事務插入的數據(虛讀)
B窗口
start transaction;
insert into account(name,money) values('ggg',1000);
commit;
-----轉到 a窗口
4.當把事務的隔離級別設置爲Serializable時,會避免所有問題
A窗口
set transaction isolation level Serializable;
start transaction;
select * from account;
-----轉到b窗口
B窗口
start transaction;
insert into account(name,money) values('ggg',1000);
-----發現不能插入,只能等待a結束事務才能插入