MySQL事務(wù)定義、起源、版本支持與提交方式全面解析
先拋出一個問題:CURD不加控制,會有什么問題?

從上面的圖我們可以看到,如果單純的CURD操作可能導(dǎo)致數(shù)據(jù)不一致的問題(線程并發(fā)問題)!
CURD滿足什么屬性,怎么解決上面的問題呢?
- 1. 買票的過程得是原子(要么買要么不買)的吧
- 2. 買票互相應(yīng)該不能影響吧
- 3. 買完票應(yīng)該要永久有效吧
- 4. 買前,和買后都要是確定的狀態(tài)吧
1、什么是事務(wù)
- 事務(wù)就是一組DML語句組成,這些語句在邏輯上存在相關(guān)性,這一組DML語句要么全部成功,要么全部失敗,是一個整體。MySQL提供一種機制,保證我們達(dá)到這樣的效果。事務(wù)還規(guī)定不同的客戶端看到的數(shù)據(jù)是不相同的。
- 事務(wù)就是要做的或所做的事情,主要用于處理操作量大,復(fù)雜度高的數(shù)據(jù)。假設(shè)一種場景:你畢業(yè)了,學(xué)校的教務(wù)系統(tǒng)后臺 MySQL 中,不在需要你的數(shù)據(jù),要刪除你的所有信息(一般不會:) ), 那么要刪除你的基本信息(姓名,電話,籍貫等)的同時,也刪除和你有關(guān)的其他信息,比如:你的各科成績,你在校表現(xiàn),甚至你在論壇發(fā)過的文章等。這樣,就需要多條 MySQL 語句構(gòu)成,那么所有這些操作合起來,就構(gòu)成了一個事務(wù)。
正如我們上面所說,一個 MySQL 數(shù)據(jù)庫,可不止你一個事務(wù)在運行,同一時刻,甚至有大量的請求被包裝成事務(wù),在向 MySQL 服務(wù)器發(fā)起事務(wù)處理請求。而每條事務(wù)至少一條 SQL ,最多很多 SQL ,這樣如果大家都訪問同樣的表數(shù)據(jù),在不加保護的情況,就絕對會出現(xiàn)問題。甚至,因為事務(wù)由多條 SQL 構(gòu)成,那么,也會存在執(zhí)行到一半出錯或者不想再執(zhí)行的情況,那么已經(jīng)執(zhí)行的怎么辦呢?
所有,一個完整的事務(wù),絕對不是簡單的 sql 集合,還需要滿足如下四個屬性:
- 原子性:一個事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會結(jié)束在中間某個環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯誤,會被回滾(Rollback)到事務(wù)開始前的狀態(tài),就像這個事務(wù)從來沒有執(zhí)行過一樣。
- 一致性:在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)規(guī)則,這包含資料的精確度、串聯(lián)性以及后續(xù)數(shù)據(jù)庫可以自發(fā)性地完成預(yù)定的工作。
- 隔離性:數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進行讀寫和修改的能力,隔離性可以防止多個事務(wù)并發(fā)執(zhí)行時由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級別,包括讀未提交( Readuncommitted )、讀提交( read committed )、可重復(fù)讀( repeatable read )和串行化( Serializable )
- 持久性:事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失。
上面四個屬性,可以簡稱為 ACID 。
- 原子性(Atomicity,或稱不可分割性)
- 一致性(Consistency)
- 隔離性(Isolation,又稱獨立性)
- 持久性(Durability)。
2、為什么會出現(xiàn)事務(wù)
事務(wù)被 MySQL 編寫者設(shè)計出來,本質(zhì)是為了當(dāng)應(yīng)用程序訪問數(shù)據(jù)庫的時候,事務(wù)能夠簡化我們的編程模型,不需要我們?nèi)タ紤]各種各樣的潛在錯誤和并發(fā)問題.可以想一下當(dāng)我們使用事務(wù)時,要么提交,要么回滾,我們不會去考慮網(wǎng)絡(luò)異常了,服務(wù)器宕機了,同時更改一個數(shù)據(jù)怎么辦對吧?因此事務(wù)本質(zhì)上是為了應(yīng)用層服務(wù)的.而不是伴隨著數(shù)據(jù)庫系統(tǒng)天生就有的.
- 備注:我們后面把 MySQL 中的一行信息,稱為一行記錄
3、事務(wù)的版本支持
在 MySQL 中只有使用了 Innodb 數(shù)據(jù)庫引擎的數(shù)據(jù)庫或表才支持事務(wù), MyISAM 不支持。
查看數(shù)據(jù)庫引擎
show engines; -- 表格顯示

show engines \G; -- 行顯示

4、事務(wù)提交方式
事務(wù)的提交方式常見的有兩種:
- 自動提交
- 手動提交
查看事務(wù)提交方式
show variables like 'autocommit';

用 SET 來改變 MySQL 的自動提交模式:
set autocommit = 0; -- 禁止自動提交

set autocommit = 1; -- 開啟自動提交

事務(wù)常見操作方式
- 使用netstat查看鏈接情況,可知:mysql本質(zhì)是一個客戶端進程

為了便于演示,我們將mysql的默認(rèn)隔離級別設(shè)置成讀未提交
set global transaction isolation level read uncommitted;

創(chuàng)建測試表
create table if not exists account(
id int primary key,
name varchar(50) not null default ' ',
balance decimal(10,2) not null default 0.0
)engine=InnoDB default charset=utf8;正常演示 - 證明事務(wù)的開始與回滾
show variables like 'autocommit'; -- 查看事務(wù)是否自動提交。我們故意設(shè)置成自動提交,看看該選項是否影響begin start transaction; -- 開始一個事務(wù)begin也可以,推薦begin savepoint s1; -- 創(chuàng)建一個保存點s1 insert into account values(1,'張三',1263.4); -- 插入一條記錄 savepoint s2; -- 創(chuàng)建一個保存點s2 insert into account values(2,'李四',6521.9); -- 再插入一條記錄 select * from account; -- 兩條記錄都在了 +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1263.40 | | 2 | 李四 | 6521.90 | +----+--------+---------+ 2 rows in set (0.00 sec) rollback to s2; -- 回滾到保存點save2 select * from account; -- id為2的一條記錄沒有了 +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1263.40 | +----+--------+---------+ 1 row in set (0.00 sec) rollback; -- 直接rollback,回滾在最開始 select * from account; -- 所有剛剛的記錄沒有了 Empty set (0.00 sec)
非正常演示1 - 證明未commit,客戶端崩潰,MySQL自動會回滾(隔離級別設(shè)置為讀未提交)
-- 終端A select * from account; -- 當(dāng)前表內(nèi)無數(shù)據(jù) show variables like 'autocommit'; -- 依舊自動提交 begin; --開啟事務(wù) insert into account values(1,'張三',1566.7); -- 插入記錄 -- 終端B select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1566.70 | +----+--------+---------+ 1 row in set (0.00 sec) -- 終端A mysql> Aborted -- ctrl + \ 異常終止MySQL -- 終端B select * from account; Empty set (0.00 sec)

非正常演示2 - 證明commit了,客戶端崩潰,MySQL數(shù)據(jù)不會在受影響,已經(jīng)持久化
show variables like 'autocommit'; -- 依舊自動提交 +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec) select * from account; -- 當(dāng)前表內(nèi)無數(shù)據(jù) Empty set (0.00 sec) begin; -- 開啟事務(wù) insert into account values (1, '張三', 1234.4); -- 插入記錄 commit; --提交事務(wù) Aborted -- ctrl + \ 異常終止MySQL --終端 B select * from account; --數(shù)據(jù)存在了,所以commit的作用是將數(shù)據(jù)持久化到MySQL中

非正常演示3 - 對比試驗。證明begin操作會自動更改提交方式,不會受MySQL是否自動提交影響
mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.01 sec) mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.01 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into account values(2,'李四',6543.2); Query OK, 1 row affected (0.00 sec) mysql> Aborted

非正常演示4 - 證明單條 SQL 與事務(wù)的關(guān)系
實驗一
mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> system clear mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec) mysql> insert into account values(2,'李四',6532.4); Query OK, 1 row affected (0.00 sec) mysql> Aborted

實驗二
mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.01 sec) mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1234.40 | +----+--------+---------+ 1 row in set (0.00 sec) mysql> insert into account values(2,'李四',3526.4); Query OK, 1 row affected (0.01 sec) mysql> select * from account; +----+--------+---------+ | id | name | balance | +----+--------+---------+ | 1 | 張三 | 1234.40 | | 2 | 李四 | 3526.40 | +----+--------+---------+ 2 rows in set (0.01 sec) mysql> Aborted

結(jié)論:
- 只要輸入begin或者start transaction,事務(wù)便必須要通過commit提交,才會持久化,與是否設(shè)置set autocommit無關(guān)。
- 事務(wù)可以手動回滾,同時,當(dāng)操作異常,MySQL會自動回滾
- 對于 InnoDB 每一條 SQL 語言都默認(rèn)封裝成事務(wù),自動提交。(select有特殊情況,因為MySQL 有 MVCC )
- 從上面的例子,我們能看到事務(wù)本身的原子性(回滾),持久性(commit)
- 那么隔離性?一致性?
事務(wù)操作注意事項
- 如果沒有設(shè)置保存點,也可以回滾,只能回滾到事務(wù)的開始。直接使用 rollback(前提是事務(wù)還沒有提交)
- 如果一個事務(wù)被提交了(commit),則不可以回退(rollback)
- 可以選擇回退到哪個保存點
- InnoDB 支持事務(wù), MyISAM 不支持事務(wù)
- 開始事務(wù)可以使 start transaction 或者 begin
總結(jié)
到此這篇關(guān)于MySQL事務(wù)定義、起源、版本支持與提交方式的文章就介紹到這了,更多相關(guān)MySQL事務(wù)詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL實現(xiàn)字符串的拼接,截取,替換,查找位置的操作
這篇文章主要介紹了MySQL實現(xiàn)字符串的拼接,截取,替換,查找位置的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
mysql取得datetime類型的數(shù)據(jù),后面會跟個.0的實現(xiàn)方法
下面小編就為大家?guī)硪黄猰ysql取得datetime類型的數(shù)據(jù),后面會跟個.0的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03
安裝Mysql5.7.10 winx64出現(xiàn)的幾個問題匯總
這篇文章主要介紹了安裝Mysql5.7.10 winx64出現(xiàn)的幾個問題匯總及解決方案,非常不錯,需要的朋友可以參考下2016-08-08
mysql 5.7.13 安裝配置方法圖文教程(win10)
這篇文章主要為大家分享了mysql 5.7.13 安裝配置方法圖文教程,感興趣的朋友可以參考一下2016-06-06
MySQL使用外鍵實現(xiàn)級聯(lián)刪除與更新的方法
這篇文章主要介紹了MySQL使用外鍵實現(xiàn)級聯(lián)刪除與更新的方法,詳細(xì)分析了mysql數(shù)據(jù)庫與表的創(chuàng)建、數(shù)據(jù)插入、查詢以及外鏈的使用與級聯(lián)操作相關(guān)技巧,需要的朋友可以參考下2016-07-07
mysql 5.7.13 winx64安裝配置方法圖文教程(win10)
這篇文章主要為大家分享了mysql 5.7.13 winx64安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01

