mysql事务 mysql事务回滚 MySQL事务死锁 如何解除死锁 资金出入账
這里寫目錄標題
- 問題
- 什么是事務
- 為什么需要事務
- 創(chuàng)建賬戶表
- 插入數(shù)據(jù)
- 無事務資金出入賬
- 有事務資金出入賬
- 事務死鎖
- 死鎖出現(xiàn)的原因
- 解決事務死鎖
- 查看表級鎖
- 查詢表鎖進程
- 查詢行級鎖
- 殺死行鎖進程
問題
最近使用golang做資金賬戶,目前涉及到這兩個問題
- 資金入賬時,可能存在提現(xiàn)【出賬】
- 資金提現(xiàn)時,可能存在資金入賬
因而,為了保證資金的正確性,這里需要事務操作。
什么是事務
MySQL 事務主要用于處理操作量大,復雜度高的數(shù)據(jù)。比如說,在人員管理系統(tǒng)中,你刪除一個人員,你既需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數(shù)據(jù)庫操作語句就構成一個事務!
為什么需要事務
以上面資金出賬和入賬為例子,寫出如下沒有事務的代碼:
創(chuàng)建賬戶表
mysql> create table account (-> id int(11) primary key not null auto_increment comment '賬戶自增主鍵id',-> userId int(11) not null comment '用戶id',-> balance int(11) not null DEFAULT 0 comment '賬戶余額,默認為0'-> ) ENGINE = 'INNODB'; Query OK, 0 rows affected (0.06 sec)由Query OK, 0 rows affected (0.06 sec)可知,account表創(chuàng)建成功。
插入數(shù)據(jù)
mysql> insert into account(userId,balance) values(1223,444),(1224,666); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0由Query OK, 2 rows affected (0.01 sec)可知,數(shù)據(jù)插入成功。
無事務資金出入賬
- 假設用戶1223給用戶1224轉賬100元。
- 若轉賬成功,用戶1223的賬戶余額為344元,用戶1224的賬戶余額為766元。
- 如果轉賬失敗,用戶1223給用戶1224的賬戶余額不變。
按照這個想法,設計如下SQL語句,此時是沒有事務的:
-- 執(zhí)行用戶1223的出賬,用戶1224的入賬 mysql> update account set balance = balance -100 where userId = 1223;update account set balance = balance + 100 where useId = 1224 ;Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0ERROR 1054 (42S22): Unknown column 'useId' in 'where clause'在兩條SQL語句中,用戶1223出賬SQL語句正確,即其賬戶余額為344元;用戶1224入賬SQL語句錯誤,因為account表中沒有useId這個字段,因而其賬戶余額不變,仍舊是666元,如下SQL所示:
mysql> select * from account; +----+--------+---------+ | id | userId | balance | +----+--------+---------+ | 1 | 1223 | 344 | | 2 | 1224 | 666 | +----+--------+---------+ 2 rows in set (0.00 sec)這就和我們的預期不同,此時,我們使用如下SQL恢復用戶1223的賬戶余額:
mysql> update account set balance = balance + 100 where userId = 1223 ;Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0然后使用事務,再次執(zhí)行上述SQL。
有事務資金出入賬
依舊是``用戶1223給用戶1224```轉賬100元,如下所示:
-- 開啟事務 mysql> begin; Query OK, 0 rows affected (0.00 sec)-- 執(zhí)行用戶1223的出賬,用戶1224的入賬 mysql> update account set balance = balance -100 where userId = 1223;update account set balance = balance + 100 where useId = 1224 ; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0ERROR 1054 (42S22): Unknown column 'useId' in 'where clause'-- 出現(xiàn)錯誤語句,回滾金額 mysql> rollback; Query OK, 0 rows affected (0.01 sec)-- 查詢回滾后的賬戶余額 mysql> select * from account; +----+--------+---------+ | id | userId | balance | +----+--------+---------+ | 1 | 1223 | 444 | | 2 | 1224 | 666 | +----+--------+---------+ 2 rows in set (0.00 sec)- 首先,開啟事務
- 執(zhí)行用戶1223的出賬,用戶1224的入賬
- 用戶1223的出賬SQL正確,用戶1224的入賬SQL錯誤
- 出現(xiàn)錯誤的SQL語句,事務回滾
- 查詢賬戶余額,發(fā)現(xiàn)賬戶余額不變,符合我們的預期。
因而,為了保證資金的正確性,我們必須使用事務。
事務死鎖
死鎖出現(xiàn)的原因
在事務的情況下,給某個賬戶加上行級鎖。
我使用的是for update的悲觀行級鎖,但前置條件是,當前賬戶要存在,否則,行級鎖就會變成表解鎖,鎖粒度就會增加。
比如,在提現(xiàn)時,需要判斷當前賬戶是否綁卡,如果沒有綁卡,就拋出您尚未綁卡的toast。一般情況下都綁了卡,但就怕特殊情況,真的是想啥來啥。恰巧遇到某用戶沒有綁卡,拋出您尚未綁卡的toast之后,再次訪問就報出如下問題:
于是去排查問題,發(fā)現(xiàn)在拋出尚未綁卡的異常時,沒有將事務回滾,于是,此處添加事務回滾tx.rollBack。
如果不進行事務回滾,那么當前行就不釋放鎖,相同的請求SQL過來,就會不停地嘗試連接,,如果連接不成功,則會拋出連接超時的問題。
當前行不釋放鎖,新的SQL請求加鎖,便出現(xiàn)了死鎖的情況。
解決事務死鎖
查看表級鎖
如果行級鎖不存在,使用SQLshow OPEN TABLES where In_use > 0查看是否存在表級鎖,如下SQL所示:
mysql> show OPEN TABLES where In_use > 0; Empty set (0.00 sec)查詢表鎖進程
其次,查詢進程(如果您有SUPER權限,您可以看到所有線程。否則,您只能看到您自己的線程)show processlist,最后殺死【kill】進程id
查詢行級鎖
使用sql語句SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;查看當前存在鎖的事務,如下圖存在一個事務死鎖:
殺死行鎖進程
殺死鎖進程,我們可以使用命令: kill trx_mysql_thread_id
比如殺死如上的行級死鎖,找到trx_mysql_thread_id的數(shù)值,執(zhí)行命令:kill 4314823
總結
以上是生活随笔為你收集整理的mysql事务 mysql事务回滚 MySQL事务死锁 如何解除死锁 资金出入账的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据库怎么查看端口号_怎么查看
- 下一篇: linux cmake编译源码,linu