mysql transaction 事務


 

1、事務簡介

  • 一個"最小的"不可再分的"工作單元"。
  • 一個事務通常對應了一個完整的業務。如:銀行的轉賬功能,a轉賬給b,a扣錢,b加錢。
  • 一個事務包含一條或多條DML語句(insert,update,delete)。
  • 在一個事務中要么所有的語句都成功執行,要么都失敗,即所有的DML語句都成功執行才會修改硬盤數據。

在mysql命令行模式下,事務是自動提交的,每執行一條DML語句都會開啟一個事務,執行成功后立即執行commit操作。可以通過"show variables like '%commit%';"  查看事務的是否自動開啟。

 

2、事務的四個屬性

① 原子性:最小的工作單元,不可再分。事務中的所有操作必須全部成功或全部失敗,成功后寫入底層數據,失敗后回滾rollback到事務開啟的狀態。

② 一致性:事務在完成時,必須使所有的數據都保持一致狀態,保持數據庫的完整性。

③ 隔離性:並發事務之間存在隔離,互不干擾。

④ 持久性:事務完成之后,它對於系統的影響是永久性的。該修改即使出現致命的系統故障也將一直保持。

 

3、事務控制語句

  • commit     事務提交
  • rollback    事務回滾
  • begin        開啟事務
  • start transaction  開啟事務 同begin
  • set transaction     設置事務隔離級別,只對當前會話有效

1)事務結束標志

  事務提交或回滾,在mysql中默認開啟自動提交事務,即執行一條insert,update,,delect,會自動提交事務

2)關閉自動提交事務的方式1

  手動開啟一個事務

begin;
    DML語句..
    DML語句..
    ...
commit/rollback;

3)關閉自動提交事務的方式2 ,這種方式最對當前會話有效。更改后通過 "show variables like '%commit%';" 查看事務開啟狀態

set autocommit = off;   # 關閉自動提交事務
set autocommit = on;   # 開啟自動提交事務

 

4、事務四個隔離級別

  • read uncommitted  讀未提交
  • read committed      讀以提交
  • repeatable  read    可重復讀
  • serializable            串行化

這四個隔離級別逐漸增高。

① read uncommitted:事務A未提交的數據,事務B也可以讀取到,這種隔離級別最低。這種事務會導致"dirty read(臟讀)"。因為事務A的數據還沒有提交,事務B就可以讀取到,那如果事務A在事務B讀取后回滾了呢,就導致了事務B讀取到的數據是"臟數據"。

② read committed:事務A未提交的數據,事務B讀取不到,事務A提交后的數據事務B才能讀取到。這個事務級別不會導致"dirty read",但會導致"不可重復讀"。假設事務A需要半天,在這期間有很多的其它事務都在修改數據,那么就導致了一個問題,事務A在開啟時讀到的數據與半天后讀到的數據差別很大,那么事務A需要在這半天內讀到的數據都是一樣的該怎么辦,比如每個月底網絡運營商系統出賬的時候,那肯定得在出賬期間讀到的數據都必須一樣才行。

③ repeatable  read:事務A提交后的數據,事務B讀取不到,事務B讀取的數據依舊是事務B剛開始時的數據。MySQL的事務默認是這個級別。

④ serializable:事務A在執行的時候,事務B只能等待,就是說當多個事務需要執行時,只能排隊一個個的來,就是串行化的字面意思了。這種隔離級別最高,但會導致數據庫的吞吐量很低一般不用。

 

5、實例

1)需要用到的表

CREATE TABLE `bank` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  `money` int(255) NOT NULL,
  PRIMARY KEY (`id`)
)
bank表
INSERT INTO `bank` VALUES (0, 'zhangsan', 1000), (0, 'lisi', 2000), (0, 'wangwu', 500), (0, 'zhaoliu', 1300);
bank表數據

2)'lisi' 給 'zhangsan' 轉賬 500

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update bank set money=money+500 where name='zhangsan';
Query OK, 1 row affected (0.01 sec)

mysql> update bank set money=money-500 where name='lisi';
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from bank;
+----+----------+-------+
| id | name     | money |
+----+----------+-------+
|  1 | zhangsan |  1500 |
|  2 | lisi     |  1500 |
|  3 | wangwu   |   500 |
|  4 | zhaoliu  |  1300 |
+----+----------+-------+
4 rows in set (0.00 sec)
View Code

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM