MySQL InnoDB 事務

MySQL 原理篇html

MySQL 索引機制sql

MySQL 體系結構及存儲引擎數據庫

MySQL 語句執行過程詳解編程

MySQL 執行計劃詳解session

MySQL InnoDB 緩衝池併發

MySQL InnoDB 事務高併發

MySQL InnoDB 鎖測試

MySQL InnoDB MVCCspa

MySQL InnoDB 實現高併發原理3d

MySQL InnoDB 快照讀在RR和RC下有何差別

MySQL5.5 及之後版本的默認存儲引擎使用的是 InnoDB,接下來針對事務的講解都是基於 InnoDB 存儲引擎的。

事務的定義

事務:數據庫操做的最小工做單元,是做爲單個邏輯工做單元執行的一系列操做; 事務是一組不可再分割的操做集合(工做邏輯單元)。

典型事務使用場景:轉帳

update user_account set balance = balance - 1000 where userID = 3; update user_account set balance = balance + 1000 where userID = 1;

MySQL 開啓事務

/* BEGIN / START TRANSACTION --手工 COMMIT / ROLLBACK --事務提交或回滾 SET SESSION autocommit = ON/OFF --設定會話級別事務是否自動開啓 */

MySQL 默認是開啓事務的,經過 SHOW VARIABLES like 'autocommit'; 能夠查看 MySQL 的事務開啓狀況。

  • 在 autocommit = ON(自動提交事務)的狀況下,能夠執行 BEGIN; 或者 START TRANSACTION; 命令,改成手動提交事務,執行完 SQL 語句後,須要經過 COMMIT 命令提交事務,或者經過 ROLLBACK 命令回滾事務。
  • 在 autocommit = OFF(手動提交事務)的狀況下,執行完 SQL 語句後,須要經過 COMMIT 命令提交事務,或者經過 ROLLBACK 命令回滾事務。

JDBC 編程

connection.setAutoCommit(boolean);

測試命令

SHOW VARIABLES like 'autocommit'; /* autocommit爲ON */
update teacher set name ='seven' where id =1; insert teacher (name,age) value ('james',22); delete from teacher where name = 'james'; /* autocommit爲ON如何開啓事務 */
BEGIN; START TRANSACTION; update teacher set name ='seven' where id =1; insert teacher (name,age) value ('james',22); delete from teacher where name = 'james'; COMMIT; ROLLBACK; /* 將autocommit改爲OFF */
set session autocommit = OFF; update teacher set name ='seven' where id =1; insert teacher (name,age) value ('james',22); delete from teacher where name = 'james'; COMMIT; ROLLBACK;

事務 ACID 特性

原子性(Atomicity):最小的工做單元,整個工做單元要麼一塊兒提交成功,要麼所有失敗回滾。

一致性(Consistency):事務中操做的數據及狀態改變是一致的,即寫入資料的結果必須徹底符合預設的規則,不會由於出現系統意外等緣由致使狀態的不一致。

隔離型(Isolation):一個事務所操做的數據在提交以前,對其餘事務的可見性設定(通常設定爲不可見)。

持久性(Durability):事務所作的修改就會永久保存,不會由於系統意外致使數據的丟失。

參考(原子性和一致性的區別是什麼?)這篇博文,講了一下原子性和一致性的區別。

事務併發帶來了哪些問題

髒讀

好比 user 表中有一條用戶數據,執行了以下操做:

  1. 事務B更新 id=1 的數據,age 更新爲18,不提交事務
  2. 事務A查詢 id=1 的數據
  3. 事務B回滾剛纔的更新操做

這個時候,事務A中查詢出的 id=1 的數據,age 的值是16仍是18?

不可重複讀

 

好比 user 表中有一條用戶數據,執行了以下操做:

  1. 事務A查詢 id=1 的數據
  2. 事務B更新 id=1 的數據,age 更新爲18,並提交事務
  3. 事務A再次查詢 id=1 的數據

這個時候,事務A兩次查詢出的 id=1 的數據,age 的值是16仍是18?

幻讀

好比在 user 表中執行了以下操做:

  1. 事務A查詢 age>15 的數據
  2. 事務B新增一條數據,age=22,並提交事務
  3. 事務A再次查詢 age>15 的數據

這個時候,事務A兩次查詢出的數據,數量是1條仍是2條?

事務四種隔離級別

SQL92 ANSI/ISO標準:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

Read Uncommitted(未提交讀 --未解決併發問題

事務未提交對其餘事務也是可見的,髒讀(dirty read)

Read Committed(提交讀) --解決髒讀問題

一個事務開始以後,只能看到本身提交的事務所作的修改,不可重複讀(non repeatable read)

Repeatable Read(可重複讀 --解決不可重複讀問題

在同一個事務中屢次讀取一樣的數據結果是同樣的,這種隔離級別未定義解決幻讀的問題

Serializable(串行化) --解決全部問題

最高的隔離級別,經過強制事務的串行執行

InnoDB 引擎對隔離級別的支持程度

事務隔離級別

髒讀

不可重複讀

幻讀

未提交讀(Read Uncommitted)

可能

可能

可能

已提交讀(Read Committed)

不可能

可能

可能

可重複讀(Repeatable Read)

不可能

不可能

對 InnoDB 不可能

串行化(Serializable)

不可能

不可能

不可能

事務隔離級別的併發能力:未提交讀 > 已提交讀 > 可重複讀 > 串行化

InnDB 引擎默認的事務隔離級別是可重複讀(Repeatable Read),在該級別中它把幻讀的問題也解決了。InnDB 中事務隔離級別經過鎖、MVCC 實現。

經過以下語句查看 InnoDB 的默認事務隔離級別:

/* 全局、當前會話的隔離級別 */
SELECT @@global.tx_isolation, @@tx_isolation;

經過以下語句設置 InnoDB 的事務隔離級別:

/* 設置全局隔離級別 */
set global transaction isolation level read committed; /* 設置當前會話的隔離級別 */
set session transaction isolation level read committed;

接下來咱們來測試一下 InnoDB 的默認事務隔離級別(Repeatable Read)是否解決了髒讀、不可重複讀、幻讀的問題。

數據準備:

CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(32) NOT NULL, `age` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; insert into `user` (`id`, `name`, `age`) values('1','Ada','16');

是否解決了髒讀的問題?

開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

  1. 事務B開啓手動事務,更新 id=1 的數據,age 更新爲18,不提交事務
  2. 事務A查詢 id=1 的數據
  3. 事務B回滾剛纔的更新操做

圖中的數字是執行步驟,經過下圖能夠看出事務A的執行結果是16,InnDB 的默認事務隔離級別完美的解決了髒讀的問題。

是否解決了不可重複讀的問題?

開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

  1. 事務A開啓手動事務,查詢 id=1 的數據
  2. 事務B更新 id=1 的數據,age 更新爲18,並提交事務
  3. 事務A再次查詢 id=1 的數據

圖中的數字是執行步驟,經過下圖能夠看出事務A兩次的執行結果都是16,沒有受事務B更新操做的影響,InnDB 的默認事務隔離級別完美的解決了不可重複讀的問題。

是否解決了幻讀的問題?

開啓兩個 MySQL 客戶端,模擬事務A和事務B的操做,執行步驟以下:

  1. 事務A開啓手動事務,查詢 age>15 的數據
  2. 事務B新增一條數據,age=22,並提交事務
  3. 事務A再次查詢 age>15 的數據

圖中的數字是執行步驟,經過下圖能夠看出事務A兩次的執行結果都是一條數據,沒有受事務B新增操做的影響,InnDB 的默認事務隔離級別完美的解決了幻讀的問題。

原文出處:https://www.cnblogs.com/yinjw/p/11880568.html

相關文章
相關標籤/搜索