mysql 数据库事务处理_MySQL数据库事务及其原理
基本概念
MySQL 事務主要用于處理操作量大,復雜度高的數據。
銀行轉賬是經典的解釋事務的例子。用戶A給用戶B轉賬5000元主要步驟可以概括為如下兩步。
第一,賬戶A賬戶減去5000元;
第二,賬戶B賬戶增加5000元;
這兩步要么成功,要么全不成功,否則都會導致數據不一致。這就可以用到事務來保證,如果是不同銀行之間的轉賬還需要用到分布式事務。
事務的特性(ACID)
(1)在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務。
(2)事務處理可以用來維護數據庫的完整性,保證成批的 SQL 語句要么全部執行,要么全部不執行。
(3)事務用來管理 insert,update,delete 語句。
原子性:構成事務的的所有操作必須是一個邏輯單元,要么全部執行,要么全部不執行。
一致性:在事務開始之前和事務結束以后,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則。
隔離性:并發事務之間不會相互影響。
持久性:事務處理結束后,對數據的修改就是永久的,即便系統故障也不會丟失。事務執行成功后必須全部寫入磁盤。
事務隔離性的實現原理
數據庫事務會導致臟讀、不可重復讀、幻讀等問題。
1、臟讀:事務還沒提交,他的修改已經被其他事務看到。
2、不可重復讀:在一個事務內讀取到了表中的某一行數據,多次讀取結果不同。
3、幻讀:同一個事務突然發現他以前沒發現的數據。幻讀是前后讀取到表中的記錄總數不一樣,讀取到了其它事務插入的數據。
事務的隔離用是通過鎖機制實現的,不同于MyISAM使用表級別的鎖,InnoDB采用更細粒度的行級別鎖,提高了數據表的性能。InnoDB的鎖通過鎖定索引來實現,如果查詢條件中有主鍵則鎖定主鍵,如果有索引則先鎖定對應索引然后再鎖定對應的主鍵(可能造成死鎖),如果連索引都沒有則會鎖定整個數據表。
MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持。MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持以及外部鍵等高級數據庫功能。
數據庫鎖
1、悲觀鎖(更新多,查詢少時用)
如果我們采用悲觀鎖。就是我們在操作數據庫時采用悲觀的態度,認為別人會在此時并發訪問數據庫。我們在查詢語句中select * from account where name=‘aaa’ for update; 等于加了排它鎖。當A查詢余額的時候,select money from account where name=‘aaa’ forupdate; 增加了排它鎖,B查詢賬戶余額的時候, select money from account wherename=‘aaa’ forupdate; 也要求對數據庫加排它鎖,因為A已經拿到了排它鎖,導致B不能加鎖,所以B只有等待A執行完畢,釋放掉鎖以后才能繼續操作。
2、樂觀鎖(更新少,查詢多時用)
如果我們采用樂觀鎖,就是我們在操作數據庫的時候會認為沒有其它用戶并發訪問,但是樂觀鎖也不是完全樂觀的,樂觀鎖是采用版本號的方式進行控制的。在數據庫表中有一列版本號。從數據庫中查詢的時候,將版本號也查詢過來,在進行更新操作的時候,將版本號加1,查詢條件的版本號還是查詢過來的版本號。比如,A執行查詢操作的時候,selectmoney,version from account where name=‘aaa’; 假設此時查詢到的版本號為0,A在進行更新操作的時候 update account set money=money+100, version=version+1where name=‘aaa’ and version=0; 未提交時B來查詢,查詢到的版本號依然是 0,B也執行更新操作update account set money=money+100,version=version+1 wherename=‘aaa’ and version=0;現在A提交了事務,B再提交事務的時候發現版本號為 0的記錄沒有了,所以就避免了數據丟失的問題。不過這種情況也導致了多個用戶更新操作時,只有一個用戶的更新被執行。
3、行級鎖(為某一條記錄加鎖)
如果想對數據庫中的某條記錄加行級鎖,那么 where 條件后面必須為索引列。否則 for update加的都是表級鎖。行級鎖就是只對要訪問的當前行加鎖,其他用戶訪問其它行記錄的時候可以訪問。 select * from accountwhere id=1 for update;
4、表級鎖(為一張表加鎖)
在查詢語句后增加 for update 時,where 條件后不是索引列,那么此時都是表級鎖。select * fromaccount where name=‘aaa’ for update;
原子性、一致性和持久性實現原理
原子性、穩定性和持久性是通過redo 和 undo 日志文件實現的,不管是redo還是undo文件都會有一個緩存我們稱之為redo_buf和undo_buf。同樣,數據庫文件也會有緩存稱之為data_buf。
undo記錄了數據在事務開始之前的值,當事務執行失敗或者ROLLBACK時可以通過undo記錄的值來恢復數據。
redo日志記錄數據修改后的值,可以避免數據在事務提交之前必須寫入到磁盤的需求,減少I/O。
事務操作
BEGIN; //開始事務,掛起自動提交
insert into t_cart_shopcart (user_id, sku_id, amount, shop_id, status) values(10001, 10001, 1, 10001, 0);
insert into t_cart_shopcart (user_id, sku_id, amount, shop_id, status) values(10001, 10002, 1, 10001, 0);
COMMIT; //提交事務,恢復自動提交
1
2
3
4
set autocommit = 0; //掛起自動提交
insert into t_cart_shopcart (user_id, sku_id, amount, shop_id, status) values(10001, 10001, 1, 10001, 0);
insert into t_cart_shopcart (user_id, sku_id, amount, shop_id, status) values(10001, 10002, 1, 10001, 0);
COMMIT; //提交事務
set autocommit = 1; //恢復自動提交
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的mysql 数据库事务处理_MySQL数据库事务及其原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oa部署mysql_oa系统部署
- 下一篇: linux cmake编译源码,linu