MySQL嵌套事務(wù)所遇到的問題
MySQL是支持嵌套事務(wù)的,但是沒多少人會這么干的…. 前段時間在國外看到一些老外在爭論MySQL嵌套事務(wù)的場景必要性。 逗死我了, 這嵌套的鬼畜用法還有啥場景必要性。 跟以前的dba同事聊過, 得知,在任何場景下都不要使用MySQL嵌套的事務(wù)。
那么使用MySQL嵌套事務(wù)會遇到什么問題 ?
mysql> select * from ceshi; +------+ | n | +------+ | 1 | +------+ 1 row in set (0.00 sec) mysql> start transaction ; Query OK, 0 rows affected (0.00 sec) mysql> insert into ceshi values(2); Query OK, 1 row affected (0.00 sec) mysql> start transaction ; Query OK, 0 rows affected (0.00 sec) mysql> insert into ceshi values(3); Query OK, 1 row affected (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.00 sec)
雖然我在最后rollback回滾了,但是數(shù)據(jù)顯示是 1 2 3 . 原本大家以為我的事務(wù)雖然是嵌套的狀態(tài),但感覺最后rollback回滾了,其實(shí)我們希望看到的結(jié)果是 子事務(wù)執(zhí)行成功,外層事務(wù)的失敗會回滾的。 但事實(shí)不是這樣的,最后的結(jié)果是 1 2 3 .
+-----+ | n | +-----+ | 1 | | 2 | | 3 | +-----+
當(dāng)sql解釋器遇到 start transaction 時候會觸發(fā)commit… !!!
begin_1 sql_1 begin_2 sql_2 sql_3 commit_1 rollback_1 .
begin_2 被執(zhí)行的時候, sql_1 已經(jīng)就被提交了, 當(dāng)你再去執(zhí)行commit_1的時候,那么sql_2 和 sql_3 就被提交了. 這時候你再去rollback,一定用都沒有…. 因?yàn)橄惹岸继峤煌炅耍隳芑貪L啥…
前面說過 在架構(gòu)上一般很少很少有人會 嵌套使用事務(wù),但有時候不小心被嵌套了。 我們拿python的項(xiàng)目來說,首先我們使用裝飾器來實(shí)現(xiàn)事務(wù)的包裝, 接著數(shù)據(jù)處理 def a() 和 def b() 函數(shù)都被事務(wù)被包裝起來, 單純的用a 和 b 都沒關(guān)系,都是單事務(wù)。 如果 a 邏輯里又調(diào)用 b, 那么會發(fā)生什么? 對的,事務(wù)嵌套了… 我想這是絕大數(shù)業(yè)務(wù)開發(fā)都會遇到的問題。
那么怎么規(guī)避這風(fēng)險 ? 可以加鎖呀…. 設(shè)立一個全局鎖,當(dāng)子事務(wù)創(chuàng)建前會判斷鎖的狀態(tài)….
如果你是flask的框架,可以使用 flask g 全局變量。
如果是django框架, 那么可以使用 thread local使用全局變量。
如果是tornado、gevent這種異步io架構(gòu),可以使用 fd 做協(xié)程變量的關(guān)聯(lián)。
@decorator
def with_transaction(f, *args, **kwargs):
db = connection.get_db_by_table("*")
try:
db.begin()
ret = f(*args, **kwargs)
db.commit()
except:
db.rollback()
raise
return ret
@with_transaction
def hide(self):
'''訂單不在app端顯示'''
if self.status not in OrderStatus.allow_deletion_statuses():
raise OrderStatusChangeNotAllowed(self.status, OrderStatus.deleted)
...
@with_transaction
def change_receipt_info(self, address, name, phone):
region = Region.get_by_address(address)
...
當(dāng)我們?nèi)?zhí)行下面語句的時候,事務(wù)會被強(qiáng)制提交. 當(dāng)然這里前提是 autocommit = True 。
ALTER FUNCTION ALTER PROCEDURE ALTER TABLE BEGIN CREATE DATABASE CREATE FUNCTION CREATE INDEX CREATE PROCEDURE CREATE TABLE DROP DATABASE DROP FUNCTION DROP INDEX DROP PROCEDURE DROP TABLE UNLOCK TABLES LOAD MASTER DATA LOCK TABLES RENAME TABLE TRUNCATE TABLE SET AUTOCOMMIT=1 START TRANSACTION
相關(guān)文章
解決Can''t locate ExtUtils/MakeMaker.pm in @INC報錯
今天小編就為大家分享一篇關(guān)于解決Can't locate ExtUtils/MakeMaker.pm in @INC報錯,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
MySQL性能優(yōu)化之Open_Table配置參數(shù)的合理配置建議
這篇文章主要介紹了MySQL性能優(yōu)化之Open_Table配置參數(shù)的合理配置建議,在MySQL數(shù)據(jù)庫中,Opened_tables表示打開過的表數(shù)量,需要的朋友可以參考下2014-07-07
Ubuntu18.0.4下mysql 8.0.20 安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Ubuntu18.0.4下mysql 8.0.19 安裝配置方法圖文教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05
mysql數(shù)據(jù)庫常見的優(yōu)化操作總結(jié)(經(jīng)驗(yàn)分享)
這篇文章主要給大家介紹了關(guān)于mysql數(shù)據(jù)庫常見的優(yōu)化操作,文章總結(jié)的都是個人日常開發(fā)使用mysql數(shù)據(jù)庫的經(jīng)驗(yàn)所得,其中包括Index索引、少用SELECT*、EXPLAIN SELECT以及開啟查詢緩存等相關(guān)資料,相信會對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-04-04
Mysql刪除幾億條數(shù)據(jù)表中的部分?jǐn)?shù)據(jù)的方法實(shí)現(xiàn)
在MySQL中刪除一個大表中的數(shù)據(jù)時,需要特別注意操作的性能和對系統(tǒng)的影響,本文主要介紹了Mysql刪除幾億條數(shù)據(jù)表中的部分?jǐn)?shù)據(jù)的方法實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下2025-03-03

