日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事务实例--银行转账

發(fā)布時間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事务实例--银行转账 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
首先,舉個例子:
銀行(bank)中有兩個客戶(name)張三和李四

我們需要將張三的1000元存款(sal)轉到李四的賬戶上

我們需要怎要通過sql語句來實現(xiàn)這個過程
update bank set sal = sal - 1000 where name = '張三';
update bank set sal = sal + 1000 where name = '李四';

但是萬一出現(xiàn)一些錯誤,比如將字段名稱打錯了,沒有檢查就執(zhí)行了這個兩個語句,比如
update bank set sal = sal - 1000 where name = '張三';
update bank set sale = sale + 1000 where name = '李四';
我們通過查詢數(shù)據(jù)庫會發(fā)現(xiàn) 張三依然減少了1000元但是李四卻沒有加錢

如果可以有一種方法使得sql語句要么都執(zhí)行,要么里面有一句沒有執(zhí)行,就全部不執(zhí)行,


這時候就要引入事務這個概念
事務是一個最小的、不可分割的工作單元,不論成功與否都作為一個整體進行工作。

事物具有哪些特性
事務都應該具備ACID特征。所謂ACID是Atomic(原子性),Consistent(一致性),Isolated(隔離性),Durable(持久性)四個詞的首字母所寫.

使用銀行轉賬來解釋一下每種特性的含義:
原子性: 組成事務處理的語句形成了一個邏輯單元,不能只執(zhí)行其中的一部分。換句話說,事務是不可分割的最小單元。 所以:銀行轉帳過程中,必須同時從一個帳戶減去轉帳金額,并加到另一個帳戶中,只改變一個帳戶是不合理的。

一致性:在事務處理執(zhí)行前后,MySQL數(shù)據(jù)庫是一致的。也就是說,事務應該正確的轉換系統(tǒng)狀態(tài)。所以:銀行轉帳過程中,要么轉帳金額從一個帳戶轉入另一個帳戶(在不考慮轉賬費用的情況下,轉賬方減少的金額與收賬方的增加的金額應該是相等),要么兩個帳戶都不變,沒有其他的情況。

隔離性:一個事務處理對另一個事務處理沒有影響。就是說任何事務都不可能看到一個處在不完整狀態(tài)下的事務。比如說,銀行轉帳過程中,在轉帳事務沒有提交之前,另一個轉帳事務只能處于等待狀態(tài)。

持久性:事務處理的效果能夠被永久保存下來。轉賬結果能夠在無論發(fā)生什么情況下都能保存下來.

Mysql支持事務的存儲引擎有:BDB、InnoDB,如果我需要使用存儲引擎則數(shù)據(jù)庫數(shù)據(jù)使用的存儲引擎應該是以上兩種。

mysql中如何使用事務


BEGIN 開始一個事務
ROLLBACK 回滾會結束用戶的事務,并撤銷正在進行的所有未提交的修改
COMMIT 提交事務,并使已對數(shù)據(jù)庫進行的所有修改成為永久性的

模擬銀行轉賬
public boolean transfrom(int fromId, int toId, double amount){Connection con = JDBCUtil.getConnection();String sql1 = "update tb_account set balance = balance - ? where userId = ?;";String sql2 = "update tb_account set balance = balance + ? where userId = ?;";String sql3 = "select balance from tb_account where userId = ?;";PreparedStatement ps1 = null;PreparedStatement ps2 = null;PreparedStatement ps3 = null;ResultSet rs = null;try{//開啟事務con.setAutoCommit(false);//轉賬時涉及的兩個賬戶以及各賬戶的金額變動ps1 = con.prepareStatement(sql1);ps1.setDouble(1, amount);ps1.setInt(2, fromId);ps1.executeUpdate();ps2 = con.prepareStatement(sql2);ps2.setDouble(1, amount);ps2.setInt(2, toId);ps2.executeUpdate();//檢查轉出方賬戶的余額是否足夠支持此次轉賬金額;如果余額不足,則拋出“余額不足”異常,并回滾ps3 = con.prepareStatement(sql3);ps3.setInt(1, fromId);rs = ps3.executeQuery();Double balance = 0.0;if(rs.next()){balance = rs.getDouble("balance");}if(balance < 0){throw new Exception("賬戶余額不足");}con.commit();return true;} catch (Exception e){e.printStackTrace();}try{con.rollback();} catch (SQLException e){e.printStackTrace();}finally{try{rs.close();ps1.close();ps2.close();ps3.close();con.close();} catch (SQLException e){e.printStackTrace();}}return false;}


SET TRANSACTION:用來設置事務的隔離級別,主要用于解決sql中的并發(fā)問題.InnoDB存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE

具體介紹四個隔離級別
1.READ UNCOMMITTED(未提交讀)。在RU的隔離級別下,事務A對數(shù)據(jù)做的修改,即使沒有提交,對于事務B來說也是可見的,這種問題叫臟讀。這是隔離程度較低的一種隔離級別,在實際運用中會引起很多問題,因此一般不常用。
2.READ COMMITTED(提交讀),一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。這個級別有時候也叫做不可重復讀,因為兩次執(zhí)行相同的查詢,可能會得到不一樣的結果。因為在這兩次讀之間可能有其他事務更改這個數(shù)據(jù),每次讀到的數(shù)據(jù)都是已經提交的。
3.REPEATABLE READ(可重復讀),解決了臟讀,也保證了在同一個事務中多次讀取同樣記錄的結果是一致的。但是理論上,可重復讀隔離級別還是無法解決另外一個幻讀的問題,指的是當某個事務在讀取某個范圍內的記錄時,另外一個事務也在該范圍內插入了新的記錄,當之前的事務再次讀取該范圍內的記錄時,會產生幻行。
4.SERIALIZABLE(可串行化),它通過強制事務串行執(zhí)行,避免了前面說的幻讀的問題,但由于讀取的每行數(shù)據(jù)都加鎖,會導致大量的鎖征用問題,因此性能也最差。
直觀地理解參考https://www.cnblogs.com/huanongying/p/7021555.html.

總結

以上是生活随笔為你收集整理的事务实例--银行转账的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。