事務-筆記整理

一、事務的概述

:

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; (查詢結果不能讀到會話已提交的記錄,讀到的是緩存中的數據);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章