關於事務
- 一、事務的概述
- 1、什麼是事務(transaction)?
- 2、關於銀行賬戶轉賬操作,賬戶轉賬是一個完整的業務,最小單元,不可再分。也就是說銀行賬戶轉賬是一個事務。
- 3、事務的四個特性(ACID):
- 4、關於術語:
- 5、提交和回滾
- 6、事務開啓的和結束的標誌?
- 7、重點:
- 二、事務的提交和回滾
- 三、事務的隔離級別
一、事務的概述
:
1、什麼是事務(transaction)?
事務:
- 一個最小的不可再分的工作單元;
- 通常一個事務對應了一個完整的業務;【例如:銀行賬戶轉賬業務,改業務就是一個最小的工作單元】
- 而一個完整的業務需要批量的DML(insert,update
,delete)語句共同聯合完成; - 事務只和DML語句有關係,或者說DML語句纔有事務;
- 以上所描述的 “批量的DML語句” 共有多少條DML語句,與業務邏輯有關係。業務邏輯不同的DML語句的個數不同。
2、關於銀行賬戶轉賬操作,賬戶轉賬是一個完整的業務,最小單元,不可再分。也就是說銀行賬戶轉賬是一個事務。
t_act 賬戶表
actno | balance |
---|---|
act-001 | 50000.0 |
act-002 | 10000.0 |
執行轉賬操作(10000):
update t_act set balance=40000.0 where actno='act-01';
update t_act set balance=20000.0 where actno='act-02';
以上的兩條DML語句要求同時成功或者同時失敗,最小單元,不可再分。當第一條DML語句執行成功之後,並不能將底層數據庫中的第一個賬戶的數據修改,只是將操作記錄了一下,這個記錄是在內存中完成同步。若第二條DML語句執行失敗,清空所有歷史操作。要完成以上的功能必須藉助事務。
3、事務的四個特性(ACID):
- 原子性 (A):
*事務是最小的工作單元,不可再分 - 一致性©:
*事務要求所有的DML語句操作的時候,必須保證同時成功或者同時失敗 - 隔離性 (I):
*事務A和事務B之間具有隔離 - 持久性(D) :
*是事務的保證,事務終結的標誌。【內存中的數據持久到硬盤文件中】
4、關於術語:
- 開啓事務:Start Transaction
- 事務結束:End Transaction
- 提交事務:Commit Transaction
- 回滾事務:Rollback Transaction
5、提交和回滾
commit; 提交:成功的結束,將所有的DML語句操作歷史記錄和底層硬盤we年中的數據來一次同步
rollback;回滾:失敗的結束,將所有的將所有的DML語句操作歷史記錄全部清空。
6、事務開啓的和結束的標誌?
- 開啓的標誌:任何一條DML(insert,update
,delete)語句的執行,標誌事物的開啓。 - 結束的標誌:提交或回滾。
7、重點:
在事務進行過程中,未結束之前,DML語句是不會更改底層數據庫文件中的數據。只是將歷史操作記錄一下,在內存中完成記錄。只有在事務結束是,而且成功結束的時候纔會修改底層硬盤文件中的數據。
二、事務的提交和回滾
8、在MYSQL數據庫管理系統中,事務的提交和回滾的演示:
- 在MYSQL數據庫管理系統中,默認情況下,事務是自動提交的,也就是說,只要執行一條DML語句,開啓了事務,並且提交了事務。
- 這種自動提交機制是可以關閉的【一下是關閉自動提交的一種方式】:
start transaction;手動開啓事務
....(DML語句)
commit/rollback;手動提交事務/手動回滾事務
- 關閉/打開自動提交的第二種方式:
set autocommit = off/on;
或者
set session autocommit = off/on;
以上打開和關閉自動提交機制 ,只對當前會話有效。
mysql> show variables like ‘%commit%’;
±----------------------------------------±------------------+
| Variable_name | Value |
±----------------------------------------±------------------+
| autocommit | ON |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_order_commits | ON |
| innodb_api_bk_commit_interval | 5 |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| original_commit_timestamp | 36028797018963968 |
| slave_preserve_commit_order | OFF |
±----------------------------------------±------------------+
set autocommit = off;
mysql> show variables like ‘%commit%’;
±----------------------------------------±------------------+
| Variable_name | Value |
±----------------------------------------±------------------+
| autocommit | OFF |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_order_commits | ON |
| innodb_api_bk_commit_interval | 5 |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| original_commit_timestamp | 36028797018963968 |
| slave_preserve_commit_order | OFF |
±----------------------------------------±------------------+
三、事務的隔離級別
9、事務的四個特性之一:隔離性 (isolation)
9.1、 事務A和事務B之間具有一定的隔離性
9.2 、隔離性有隔離級別(4個):
- read uncommittd 讀未提交
- read committd 讀已提交
- repeatable read可重複讀
- serializable 串行化
9.3、read uncommittd 讀未提交
- 事務A和事務B,事務A未提交的數據,事務B可以讀取到。
- 這裏讀取到的數據可以叫做“髒數據”,或者叫做“Dirty Read”.
- 這種隔離級別是最低級別,這種級別一般都是在理論上存在的,數據庫默認的隔離級別一般都改與該隔離級別的。
9.4、 read committd 讀已提交
- 事務A和事務B,事務A提交的數據,事務B才能讀取到。
- 這種隔離級別高於上面的讀未提交。
- 換句話說:對方事務提交之後的數據,我當前事務才能夠讀取到。
- 這種隔離級別可以避免髒數據。
- 這種隔離級別會導致:“不可重複讀取”。
- Oracle數據庫管理系統默認的隔離級別就是:讀已提交。
9.5、repeatable read 可重複讀
- 事務A和事務B,事務A提交之後的數據,事務B讀取不到。
- 事務B 是可重複讀取數據的。
- 這種隔離級別高於讀已提交。
- 換句話說:對方事務提交之後的數據,我當前事務還是讀取不到。
- 這種隔離級別可以避免:“髒讀和不可重複讀取”,達到可重複讀取。
- MySQL數據庫管理系統默認的隔離級別就是: 可重複讀。
- 雖然可以達到“可重複讀”的效果,但是會導致“幻想讀”。
9.6、serializable 串行化
- 事務A和事務B,事務A在操作數據庫表中數據的時候,事務B只能排隊。
- 這種事務隔離級別一般很少使用,吞吐量太低,用戶體驗不好。
- 這種隔離級別可以避免“幻想讀”,每一次讀取的都是數據庫中的真實記錄。
- 事務A和事務B不再併發。
9.7、隔離級別與一致性問題的關係
隔離級別 | 髒讀取 | 不可重複讀 | 幻想讀 |
---|---|---|---|
讀未提交 | 可能 | 可能 | 可能 |
讀已提交 | 不可能 | 可能 | 可能 |
可重複讀 | 不可能 | 不可能 | 對InnoDB不可能 |
串行化 | 不可能 | 不可能 | 不可能 |
10、設置事務的隔離級別
10.1、 第一種方式:修改my.ini配置文件
可選值:
- read uncommittd 讀未提交
- read committd 讀已提交
- repeatable read可重複讀
- serializable 串行化
--------------------my.ini------------------------------
[mysqld]
transaction-isolation=READ-COMMITTED
---------------------my.ini------------------------------
10.2、 第二種方式:使用命令方式設置事務的隔離級別
可選值:
- read uncommittd 讀未提交
- read committd 讀已提交
- repeatable read可重複讀
命令格式:
set <無 / session / global > transaction isolation level ;
設置事務的隔離級別作用於全局:
set global transaction isolation level ;
設置事務的隔離級別作用於當前會話:
set transaction isolation level ;
或者
set session transaction isolation level ;
11、查看隔離級別
- 查看會話級隔離級別:
方式一:select @@transaction_isolation;
方式二:show variables like ‘transaction_isolation’;
或者
方式一:select @@session.transaction_isolation; - 查看全局級隔離級別:
select @@global.transaction_isolation;
12、併發事務與隔離級別示例
12.1、讀未提交read uncommitted
會話1 | 會話2 |
---|---|
set global transaction isolation level read uncommitted; | |
退出DOS窗口 | |
use bjpowernode; | use bjpowernode; |
start transaction; | start transaction; |
insert into t_ueser(name) values(‘king’); | select * from t_user(查詢結果可以讀到會話一未提交的記錄); |
12.2、讀已提交read committed
會話1 | 會話2 |
---|---|
set global transaction isolation level read committed; | |
退出DOS窗口 | |
use bjpowernode; | use bjpowernode; |
start transaction; | start transaction; |
insert into t_ueser(name) values(‘Ford’); | select * from t_user;(查詢結果不能讀到會話一未提交的記錄); |
commit; | select * from t_user; (查詢結果可以讀到會話已提交的記錄); |
12.3、可重複復repeatable read
會話1 | 會話2 |
---|---|
set global transaction isolation level repeatable read; | |
退出DOS窗口 | |
use bjpowernode; | use bjpowernode; |
start transaction; | start transaction; |
insert into t_ueser(name) values(‘luzhishen’); | |
commit; | select * from t_user; (查詢結果不能讀到會話已提交的記錄,讀到的是緩存中的數據); |