🍖數據庫事務(Transaction)詳解

一.事務

1.什麼是事務

  • 事務是由一條或多條SQL語句組成的邏輯執行單元, 能夠比喻成一個容器, 裏面放的就是一堆SQL語句, 這些語句要麼所有執行成功, 要麼一個都沒法執行成功(原子性)

2.爲何使用事務

  • 對數據進行一系列的操做的時候, 爲了防止這些操做中部分操做成功而另外一些操做失敗, 從而形成數據的不正確性, 這個時候咱們就須要使用事務將其回滾到原來的狀態

3.如何使用事務

  • 關鍵字
🍎開啓事務
begin;  # 或者下面的語句  
start transaction;

🍎事務回滾(回滾到以前的狀態,並關閉事務)
rollback;  # 回滾 + 關閉

🍎事務提交(將修改提交,並關閉事務)
commit;    # 提交 + 關閉

由上面關鍵字能夠看出, 一個事務的開始對應一個回滾或者提交, 以後就須要從新開啓事務python

  • 銀行餘額示例
🍎先建立一個用戶餘額表並插入記錄
create table user(
    id int primary key auto_increment,
    name varchar(16) not null,
    balance int not null
);

insert user(name,balance) value
    ("shawn",150000),
    ("song",20000),
    ("xing",520022),
    ("hai",10000);

select * from user;  # 查看一下全部記錄

🍎開啓事務
begin;  # 或者 start transaction;

🍎更新記錄
update user set balance=100 where name="shawn";
update user set balance=100 where name="song";
update user set balance=100 where name="xing";
update user set balance=200 where name="hai";

select * from user;  # 查看一下是否修改爲功

🍎事務回滾
rollback;  # 回滾以後, 該事務就關閉了
select * from user;  # 查看一下是否回滾到原來的數據

🍎再開啓一個事務
begin;

🍎再次對數據進行更新
update user set balance=200 where name="shawn";
update user set balance=200 where name="song";
commit;  # 事務提交, 並關閉了該事務
select * from user;  # 查看數據的變化

rollback;  # 再次使用事務回滾將不在起做用, 由於事務已經關閉了 
select * from user;

image-20210214124605661

image-20210214124833697

image-20210214125609578

  • pymysql 實現事務處理實例
select * from user where id=1;

image-20210226154121496

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123456",
    database="test02",
    charset="utf8"
)

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql1 = "select * from user;"
sql2 = "update user set name=%s where id=1;"
sql3 = "select * from user;"

try:
    cursor.execute(sql1)  # 執行 sql1
    print(cursor.fetchall())
    rows = cursor.execute(sql2,("song",))  # 執行sql2
    print("row : %s"%rows)
    cursor.execute(sql3)  # 執行 sql3
    print(cursor.fetchall())
except Exception as E:
    conn.rollback()  # 事務回滾 (在pymysql其實能夠不用回滾,檢測到異常這一段就結束了不會提交)
    print(f"執行失敗 : {E}")
else:
    conn.commit()    # 事務提交

cursor.close()
conn.close()

image-20210226154506004

二.事務的四大特徵 (ACID)

1.原子性(Atomicity)

  • 事務是一段程序的最小執行單元, 不可再分(就如同天然界的原子不可再分), 因此事務中的操做要麼都成功, 要麼都失敗

2.一致性(Consistency)

  • 事務的執行, 必須使數據庫從一個一致性狀態, 變成另外一個一致性狀態, 一致性是經過原子性來保證的

3.隔離性(Lsolation)

  • 各個事務的執行互不干擾, 任意一個事務的內部操做對其餘併發的事務, 都是隔離的; 也就是說 : 併發執行的事務之間不能看到對方的中間狀態, 併發執行的事務之間不能相互影響

4.持續性(Durability)

  • 也叫"持久性", 指事務一旦提交, 對數據的任何改變都記錄到永久存儲器中, 一般是物理數據庫

三.事務的三種運行模式

隱式能夠比喻成自動mysql

顯式能夠比喻成手動sql

1.自動提交事務 (隱式開啓,隱式提交)

每條單獨的SQL語句都是一個事務, 語句執行完以後會自動執行 commit 操做, 若是出現錯誤則進行事務回滾至以前的狀態數據庫

  • mysql 默認開啓自動提交事務, 可經過下面語句來開啓或關閉自動提交事務模式
set session autocommit=0;  
# 0 是關閉, 1 是開啓
# [session 是當前會話變量 \ global 是全局變量]
  • SQL server 默認開啓自動提交事務, 經過下面語句來關閉或開啓
set implicit_transactions ON;  
# ON 是打開隱式事務模式或關閉自動事務模式
# OFF 是關閉隱式事務模式或打開自動提交事務模式
  • Oracle 默認顯示提交事務, 經過下面語句開啓或關閉自動提交事務模式
set autocommit on;
# on是開啓自動事務模式
# off是關閉自動提交事務模式

2.顯式事務 (顯式開啓,顯式提交)

經過指定事務開始語句來顯示的開啓事務, 並由提交或者回滾命令來結束事務session

  • mysqlstart transaction 或者 begin 語句開始事務, 以 commit 或者 rollback 語句結束事務

3.隱式事務 (隱式開啓,顯示提交)

在隱式事務中, 不須要使用 begin 或者 start transaction 來開啓事務, 每一個 SQL 語句第一次執行會自動開啓事務, 但須要使用 commit 提交或者 rollback 回滾來結束事務併發

  • mysql 中經過關閉自動提交事務, 從而來達到隱式開啓事務, 顯示提交事務的目的
set session autocommit=0;
# 0 是關閉, 1 是開啓
# [session 是當前會話變量 \ global 是全局變量]

4.總結

MySQL 默認爲每條 SQL 語句開啓事務, 而且會在本條 SQL 執行完畢後自動執行 commit 操做進行提交, 設置手動提交的兩種方式:fetch

  • 直接設置 Mysql 的提交模式
set session|global autocommit=0  # 禁止自動提交
set session|global autocommit=1  # 開啓自動提交
  • 手動開啓事務
begin;   # 或者 start transaction;
    [SQL語句]
commit;  # 或者 rollback;

四.事務保存點 (savepoint)

1.什麼是事務的保存點

  • savepoint 相似於虛擬機中的快照, 運用於事務中
  • 每設置一個 savepoint 就是一個保存點
  • 當事務結束時會自動刪除定義的全部保存點
  • 在事務沒有結束以前能夠回退到任意保存點

2.設置和回滾保存點語法

savepoint [保存點名字];        # 設置保存點
rollback to [某個保存點名字];  # 回滾到某個保存點,該保存點以後的操做都無效包括保存點
rollback;  # 回滾開啓事務後的全部操做,並刪除全部保存點,並結束事務

3.事務保存點實驗

  • 設置保存點, 能夠設置不少個(one、two、three)
begin;
select * from user;
update user set name="shawn" where id=1;
savepoint one;
select * from user;
update user set name="xxxx" where id=3;
savepoint two;
select * from user;
delete from user where id>3;
savepoint three;
select * from user;

image-20210226185151636

image-20210226190013451

  • 回退到某個保存點, 能夠跨越多個保存點
rollback to two;
select * from user;

image-20210226190701117

  • 保存點 two 以後建立的保存點 three 也失效了
rollback to three;

image-20210226190850751

  • rollback 回滾全部
rollback

image-20210226191136992

五.事務使用的原則

  • 保持事務短小
  • 儘可能避免事務中的 rollback
  • 儘可能避免 savepoint
  • 顯式聲明打開事務
  • 默認狀況下,依賴於悲觀鎖,爲吞吐量要求苛刻的事務考慮樂觀鎖
  • 鎖的行越少越好,鎖的時間越短越好

---end---atom

相關文章
相關標籤/搜索