MySQL事務(wù)的四種特性總結(jié)
一、事務(wù)的概念
1、事務(wù)的四種特性
事務(wù)就是一組DML語句組成,這些語句在邏輯上存在相關(guān)性,這一組DML語句要么全部成功,要么全部失敗,是一個(gè)整體。例如銀行轉(zhuǎn)賬操作,上層看來是一個(gè)單純的轉(zhuǎn)賬操作,但是下層卻需要一條或多條SQL語句來完成轉(zhuǎn)賬操作,這一組SQL是一個(gè)整體,被稱為事務(wù)。事務(wù)還規(guī)定不同的客戶端看到的數(shù)據(jù)是不相同的。
一個(gè) MySQL 數(shù)據(jù)庫,可不止你一個(gè)事務(wù)在運(yùn)行,同一時(shí)刻,有大量的請(qǐng)求被包裝成事務(wù),向 MySQL 服務(wù)器發(fā)起事務(wù)處理請(qǐng)求。如果多名用戶都訪問同樣的表數(shù)據(jù),在不加保護(hù)的情況,絕對(duì)會(huì)出現(xiàn)問題。并且事務(wù)由多條 SQL 構(gòu)成,也會(huì)存在執(zhí)行到一半出錯(cuò)或者不想再執(zhí)行的情況,那么已經(jīng)執(zhí)行的怎么辦呢?
所以一個(gè)完整的事務(wù),絕對(duì)不是簡(jiǎn)單的 sql 集合,還需要滿足如下四個(gè)屬性:
原子性:一個(gè)事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開始前的狀態(tài),就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣。
一致性:在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)規(guī)則,這包含資料的精確度、串聯(lián)性以及后續(xù)數(shù)據(jù)庫可以自發(fā)性地完成預(yù)定的工作。 原子性、隔離性、持久性是因,一致性是果。
隔離性:數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級(jí)別,包括讀未提交( Read uncommitted )、讀提交( read committed )、可重復(fù)讀( repeatable read )和串行化( Serializable )
持久性:事務(wù)處理結(jié)束后,對(duì)數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失。
上面四個(gè)屬性,可以簡(jiǎn)稱為 ACID 。
原子性(Atomicity,或稱不可分割性)
一致性(Consistency)
隔離性(Isolation,又稱獨(dú)立性)
持久性(Durability)。
2、事務(wù)的作用
當(dāng)程序員在編寫上層代碼邏輯訪問數(shù)據(jù)庫時(shí),事務(wù)能夠簡(jiǎn)化編程時(shí)需要考慮的多種細(xì)節(jié)問題,例如我們?cè)谑褂檬聞?wù)時(shí),要么提交要么回滾,不用去擔(dān)心網(wǎng)絡(luò)異常、服務(wù)器宕機(jī)等問題。
3、存儲(chǔ)引擎對(duì)事務(wù)的支持
在 MySQL 中只有Innodb支持事務(wù),而MyISAM不支持。
4、事務(wù)的提交方式
自動(dòng)提交:
–查看MySQL事務(wù)的提交方式發(fā)現(xiàn)是自動(dòng)提交
```mysql ##查看MySQL事務(wù)的提交方式發(fā)現(xiàn)是自動(dòng)提交 mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.02 sec)
**使用set改變MySQL的事務(wù)提交方式**: ```sql ##將MySQL的事務(wù)提交方式修改為禁止自動(dòng)提交 mysql> set autocommit=0; Query OK, 0 rows affected (0.01 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec) ##將MySQL的事務(wù)提交方式修改為開啟自動(dòng)提交 mysql> set autocommit=1; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec)
二、事務(wù)的啟動(dòng)、回滾與提交
1、準(zhǔn)備工作:調(diào)整MySQL的默認(rèn)隔離級(jí)別為最低/創(chuàng)建測(cè)試表
為了看到演示現(xiàn)象,先將MySQL的默認(rèn)隔離級(jí)別設(shè)置成讀未提交(最低)后退出重啟:
mysql> set global transaction isolation level read uncommitted; Query OK, 0 rows affected (0.00 sec) ##修改默認(rèn)隔離級(jí)別生效 mysql> select @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set, 1 warning (0.00 sec)
創(chuàng)建測(cè)試表:
create table if not exists account( id int primary key, name varchar(50) not null default '', blance decimal(10,2) not null default 0.0 )ENGINE=InnoDB DEFAULT CHARSET=UTF8;
2、證明事務(wù)的開始與回滾
mysql> start transaction; -- 開始一個(gè)事務(wù)begin也可以,推薦begin Query OK, 0 rows affected (0.00 sec) mysql> savepoint save1; -- 創(chuàng)建一個(gè)保存點(diǎn)save1 Query OK, 0 rows affected (0.00 sec) mysql> insert into account values (1, '張三', 1030.00); -- 插入一條記錄 Query OK, 1 row affected (0.05 sec) mysql> savepoint save2; -- 創(chuàng)建一個(gè)保存點(diǎn)save2 Query OK, 0 rows affected (0.01 sec) mysql> insert into account values (2, '李四', 13000.00); -- 在插入一條記錄 Query OK, 1 row affected (0.00 sec) mysql> select * from account; -- 兩條記錄都在了 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 1030.00 | | 2 | 李四 | 13000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> rollback to save2; -- 回滾到保存點(diǎn)save2 Query OK, 0 rows affected (0.03 sec) mysql> select * from account; -- 一條記錄沒有了 +----+--------+--------+ | id | name | blance | +----+--------+--------+ | 1 | 張三 | 100.00 | +----+--------+--------+ 1 row in set (0.00 sec) mysql> rollback; -- 直接rollback,回滾在最開始 Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 所有剛剛的記錄沒有了 Empty set (0.00 sec)
3、證明未commit,客戶端崩潰,mysql自動(dòng)回滾(隔離級(jí)別設(shè)置為未提交)
-- 終端A mysql> select * from account; -- 當(dāng)前表內(nèi)無數(shù)據(jù) Empty set (0.00 sec) mysql> show variables like 'autocommit'; -- 依舊自動(dòng)提交 +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec) mysql> begin; -- 開啟事務(wù) Query OK, 0 rows affected (0.00 sec) mysql> insert into account values (1, '張三', 100.30); -- 插入記錄 Query OK, 1 row affected (0.00 sec) mysql> select * from account; -- 數(shù)據(jù)已經(jīng)存在,但沒有commit,此時(shí)同時(shí)查看 -- 終端B +----+--------+--------+ | id | name | blance | +----+--------+--------+ | 1 | 張三 | 100.30 | +----+--------+--------+ 1 row in set (0.00 sec) mysql> Aborted -- ctrl + \ 異常終止MySQL -- 終端B mysql> select * from account; -- 終端A崩潰前 +----+--------+--------+ | id | name | blance | +----+--------+--------+ | 1 | 張三 | 100.30 | +----+--------+--------+ 1 row in set (0.00 sec) mysql> select * from account; -- 數(shù)據(jù)自動(dòng)回滾 Empty set (0.00 sec)
結(jié)論:
1、autocommit并不會(huì)影響begin后啟動(dòng)的事務(wù)的提交,使用begin后必須輸入commit才能使數(shù)據(jù)持久化。
2、單句SQL本質(zhì)就是事務(wù),它的持久化和autocommit有關(guān),autocommit為ON,表示單SQL無需手動(dòng)commit自動(dòng)提交,否則需要手動(dòng)commit令數(shù)據(jù)持久化。(select有特殊情況,因?yàn)镸ySQL 有 MVCC )
3、事務(wù)可以手動(dòng)回滾,同時(shí),當(dāng)操作異常,MySQL會(huì)自動(dòng)回滾
4、我們能看到事務(wù)本身的原子性(rollback),持久性(commit)
三、事務(wù)的隔離級(jí)別
1、隔離性
1、MySQL服務(wù)可能會(huì)同時(shí)被多個(gè)客戶端進(jìn)程(線程)訪問,訪問的方式以事務(wù)方式進(jìn)行。
2、一個(gè)事務(wù)可能由多條SQL構(gòu)成,也就意味著,任何一個(gè)事務(wù),都有執(zhí)行前,執(zhí)行中,執(zhí)行后的階段。而所謂的原子性,其實(shí)就是讓用戶層,要么看到執(zhí)行前,要么看到執(zhí)行后。執(zhí)行中出現(xiàn)問題,可以隨時(shí)回滾。所以單個(gè)事務(wù),對(duì)用戶表現(xiàn)出來的特性,就是原子性。
3、但是所有事務(wù)都要有個(gè)執(zhí)行過程,那么在多個(gè)事務(wù)各自執(zhí)行多個(gè)SQL的時(shí)候,就還是有可能會(huì)出現(xiàn)互相影響的情況。比如:多個(gè)事務(wù)同時(shí)訪問同一張表,甚至同一行數(shù)據(jù)。
4、數(shù)據(jù)庫中,為了保證事務(wù)執(zhí)行過程中盡量不受干擾,就有了一個(gè)重要特征:隔離性 。
5、數(shù)據(jù)庫中,允許事務(wù)受不同程度的干擾,就有了一種重要特征:隔離級(jí)別
2、隔離級(jí)別
讀未提交【Read Uncommitted】: 在該隔離級(jí)別,所有的事務(wù)都可以看到其他事務(wù)沒有提交的執(zhí)行結(jié)果。(實(shí)際生產(chǎn)中不可能使用這種隔離級(jí)別的),但是相當(dāng)于沒有任何隔離性,也會(huì)有很多并發(fā)問題,如臟讀,幻讀,不可重復(fù)讀等,我們上面為了做實(shí)驗(yàn)方便,用的就是這個(gè)隔離性。
讀提交【Read Committed】:該隔離級(jí)別是大多數(shù)數(shù)據(jù)庫的默認(rèn)的隔離級(jí)別(不是 MySQL 默認(rèn)的)。它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看到其他的已經(jīng)提交的事務(wù)所做的改變。這種隔離級(jí)別會(huì)引起不可重復(fù)讀,即一個(gè)事務(wù)執(zhí)行時(shí),如果多次 select,可能得到不同的結(jié)果。
可重復(fù)讀【Repeatable Read】: 這是 MySQL 默認(rèn)的隔離級(jí)別,它確保同一個(gè)事務(wù),在執(zhí)行中,多次讀取操作數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行。但是有的數(shù)據(jù)庫會(huì)有幻讀問題。(MySQL不會(huì))
串行化【Serializable】: 這是事務(wù)的最高隔離級(jí)別,它通過強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決了幻讀的問題。它在每個(gè)讀的數(shù)據(jù)行上面加上共享鎖。但是可能會(huì)導(dǎo)致超時(shí)和鎖競(jìng)爭(zhēng)(這種隔離級(jí)別太極端,實(shí)際生產(chǎn)基本不使用)
隔離級(jí)別如何實(shí)現(xiàn):隔離,基本都是通過鎖實(shí)現(xiàn)的,不同的隔離級(jí)別,鎖的使用是不同的。常見有,表鎖,行鎖,讀鎖,寫鎖,間隙鎖(GAP),Next-Key鎖(GAP+行鎖)等。
3、隔離級(jí)別的查看與設(shè)置隔離性
3.1查看隔離性
-- 查看 mysql> SELECT @@global.tx_isolation; --查看全局隔級(jí)別 +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; --查看會(huì)話(當(dāng)前)全局隔級(jí)別 +------------------------+ | @@session.tx_isolation | +------------------------+ | REPEATABLE-READ | +------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@tx_isolation; --默認(rèn)同上 +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set, 1 warning (0.00 sec)
3.2、設(shè)置隔離性
語法:
-- 設(shè)置當(dāng)前會(huì)話 or 全局隔離級(jí)別語法 SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
設(shè)置會(huì)話的隔離級(jí)別為串行化:
--設(shè)置當(dāng)前會(huì)話隔離性,另起一個(gè)會(huì)話,看不多,只影響當(dāng)前會(huì)話 mysql> set session transaction isolation level serializable; -- 串行化 Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@global.tx_isolation; --全局隔離性還是RR +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; --會(huì)話隔離性成為串行化 +------------------------+ | @@session.tx_isolation | +------------------------+ | SERIALIZABLE | +------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@tx_isolation; --同上 +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set, 1 warning (0.00 sec)
–設(shè)置全局隔離性,另起一個(gè)會(huì)話,會(huì)被影響
mysql> set global transaction isolation level READ UNCOMMITTED; Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | READ-UNCOMMITTED | +-----------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@session.tx_isolation; +------------------------+ | @@session.tx_isolation | +------------------------+ | READ-UNCOMMITTED | +------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> SELECT @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set, 1 warning (0.00 sec) -- 注意,如果沒有現(xiàn)象,關(guān)閉mysql客戶端,重新連接。
當(dāng)一個(gè)會(huì)話修改了全局隔離級(jí)別,將會(huì)同時(shí)修改其他所有會(huì)話的全局隔離級(jí)別。
后續(xù)登錄時(shí),會(huì)話和默認(rèn)的隔離級(jí)別將會(huì)引用全局隔離級(jí)別的設(shè)置。
盡量保證隔離級(jí)別一致,閑的沒事不要改事務(wù)的隔離級(jí)別。
4、四種隔離級(jí)別詳解
4.1、讀未提交【Read Uncommitted】
--先設(shè)置當(dāng)前的全局隔離級(jí)別為讀未提交,再退出MySQL重新登錄一下讓其生效 mysql> set global transaction isolation level read uncommitted; Query OK, 0 rows affected (0.01 sec)
本文第二章就是用讀未提交來舉例的。
在多個(gè)并行的會(huì)話中啟動(dòng)事務(wù),一個(gè)事務(wù)在改動(dòng)數(shù)據(jù)庫哪怕沒有commit提交,其他事務(wù)也是能夠?qū)崟r(shí)的看到它修改的數(shù)據(jù)。一個(gè)事務(wù)在執(zhí)行中,讀到另一個(gè)執(zhí)行中事務(wù)的更新(或其他操作)但是未commit的數(shù)據(jù),這種不合理的現(xiàn)象叫做臟讀(dirty read)
讀未提交的其他不合理現(xiàn)象還有不可重復(fù)讀、幻讀
讀未提交幾乎沒有加鎖,雖然效率高,但是問題太多,嚴(yán)重不建議采用。
4.2、讀提交【Read Committed】
-- 終端A mysql> set global transaction isolation level read committed; Query OK, 0 rows affected (0.00 sec) -- 重啟客戶端 mysql> select * from account; -- 查看當(dāng)前數(shù)據(jù) +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 123.00 | | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> begin; -- 手動(dòng)開啟事務(wù),同步的開始終端B事務(wù) Query OK, 0 rows affected (0.00 sec) mysql> update account set blance=321.0 where id=1; -- 更新張三數(shù)據(jù) Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 --切換終端到終端B,查看數(shù)據(jù)。 mysql> commit; --commit提交! Query OK, 0 rows affected (0.01 sec) -- 切換終端到終端B,再次查看數(shù)據(jù)。 -- 終端B mysql> begin; -- 手動(dòng)開啟事務(wù),和終端A一前一后 Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 終端A commit之前,查看不到 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 123.00 | -- 老的值 | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) -- 終端A commit之后,看到了! -- but,此時(shí)還在當(dāng)前事務(wù)中,并未commit,那么就造成了,同一個(gè)事務(wù)內(nèi),同樣的讀取,在不同的時(shí)間段 ##(依舊還在事務(wù)操作中!),讀取到了不同的值,這種現(xiàn)象叫做不可重復(fù)讀(non reapeatable read)!! ##(這個(gè)是問題嗎??) mysql> select *from account; +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 321.00 | -- 新的值 | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec)
通過試驗(yàn)可以發(fā)現(xiàn)讀提交級(jí)別,事務(wù)A在commit提交事務(wù)之前,所做的修改是不會(huì)被其他事務(wù)看到的,一旦事務(wù)A發(fā)起commit之后,其他事務(wù)就能看到事務(wù)A對(duì)數(shù)據(jù)的修改。這就造成了其他事務(wù)在不同的時(shí)間點(diǎn)select查看數(shù)據(jù)庫時(shí),會(huì)查到不同的數(shù)據(jù)。這種現(xiàn)象叫不可重復(fù)讀。(事務(wù)中的讀取不是原子的)
4.3、可重復(fù)讀【Repeatable Read】
進(jìn)行插入操作:
-- 終端A mysql> set global transaction isolation level repeatable read; -- 設(shè)置全局隔離級(jí)別 RR Query OK, 0 rows affected (0.01 sec) -- 關(guān)閉終端重啟 mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | -- 隔離級(jí)別RR +-----------------+ 1 row in set, 1 warning (0.00 sec) -- 終端A mysql> select *from account; +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 321.00 | | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> begin; -- 開啟事務(wù),終端B同步開啟 Query OK, 0 rows affected (0.00 sec) mysql> insert into account (id,name,blance) values(3, '王五', 5432.0); Query OK, 1 row affected (0.00 sec) -- 切換到終端B,查看另一個(gè)事務(wù)是否能看到 mysql> commit; -- 提交事務(wù) Query OK, 0 rows affected (0.00 sec) -- 切換終端到終端B,查看數(shù)據(jù)。 mysql> select * from account; +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | | 3 | 王五 | 5432.00 | +----+--------+----------+ 3 rows in set (0.00 sec) -- 終端B mysql> begin; -- 開啟事務(wù) Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 終端A commit前 查看 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> select * from account; -- 終端A commit后 查看 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> select * from account; +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | +----+--------+----------+ 2 rows in set (0.00 sec) mysql> commit; -- 結(jié)束事務(wù) Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 看到更新 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | | 3 | 王五 | 5432.00 | +----+--------+----------+ 3 rows in set (0.00 sec)
多次查看,發(fā)現(xiàn)終端A在對(duì)應(yīng)事務(wù)中insert的數(shù)據(jù),在終端B的事務(wù)周期中,也沒有什么影響,也符合可重復(fù)的特點(diǎn)。但是,一般的數(shù)據(jù)庫在可重復(fù)讀情況的時(shí)候,無法屏蔽其他事務(wù)insert的數(shù)據(jù)(為什么?因?yàn)楦綦x性實(shí)現(xiàn)是對(duì)數(shù)據(jù)加鎖完成的,而insert待插入的數(shù)據(jù)因?yàn)椴⒉淮嬖?,那么一般加鎖無法屏蔽這類問題),會(huì)造成雖然大部分內(nèi)容是可重復(fù)讀的,但是insert的數(shù)據(jù)在可重復(fù)讀情況被讀取出來,導(dǎo)致多次查找時(shí),會(huì)多查找出來新的記錄,就如同產(chǎn)生了幻覺。這種現(xiàn)象,叫做幻讀(phantom read)。很明顯,MySQL在RR級(jí)別的時(shí)候,是解決了幻讀問題的(解決的方式是用Next-Key鎖(GAP+行鎖)解決的。這塊比較難,有興趣同學(xué)了解一下)。
4.4、串行化
-- 對(duì)所有操作全部加鎖,進(jìn)行串行化,不會(huì)有問題,但是只要串行化,效率很低,幾乎完全不會(huì)被采用 -- 終端A mysql> set global transaction isolation level serializable; Query OK, 0 rows affected (0.00 sec) mysql> select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set, 1 warning (0.00 sec) mysql> begin; -- 開啟事務(wù),終端B同步開啟 Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 兩個(gè)讀取不會(huì)串行化,共享鎖 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | | 3 | 王五 | 5432.00 | +----+--------+----------+ 3 rows in set (0.00 sec) mysql> update account set blance=1.00 where id=1; -- 終端A中有更新或者其他操作,會(huì)阻 ##塞。直到終端B事務(wù)提交。 Query OK, 1 row affected (18.19 sec) Rows matched: 1 Changed: 1 Warnings: 0 -- 終端B mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from account; -- 兩個(gè)讀取不會(huì)串行化 +----+--------+----------+ | id | name | blance | +----+--------+----------+ | 1 | 張三 | 4321.00 | | 2 | 李四 | 10000.00 | | 3 | 王五 | 5432.00 | +----+--------+----------+ 3 rows in set (0.00 sec) mysql> commit; -- 提交之后,終端A中的update才會(huì)提交。 Query OK, 0 rows affected (0.00 sec)
結(jié)論:
其中隔離級(jí)別越嚴(yán)格,安全性越高,但數(shù)據(jù)庫的并發(fā)性能也就越低,往往需要在兩者之間找一個(gè)平
衡點(diǎn)。
不可重復(fù)讀的重點(diǎn)是修改和刪除:同樣的條件, 你讀取過的數(shù)據(jù),再次讀取出來發(fā)現(xiàn)值不一樣了
幻讀的重點(diǎn)在于新增:同樣的條件, 第1次和第2次讀出來的記錄數(shù)不一樣
說明: mysql 默認(rèn)的隔離級(jí)別是可重復(fù)讀,一般情況下不要修改
上面的例子可以看出,事務(wù)也有長(zhǎng)短事務(wù)這樣的概念。事務(wù)間互相影響,指的是事務(wù)在并行執(zhí)行的
時(shí)候,即都沒有commit的時(shí)候,影響會(huì)比較大
以上就是MySQL事務(wù)的四種特性總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于MySQL事務(wù)特性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
windows下mysql中binlog日志分析和數(shù)據(jù)恢復(fù)問題
這篇文章主要介紹了windows下mysql中binlog日志分析和數(shù)據(jù)恢復(fù)問題,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06阿里云Linux CentOS 7.2下自建MySQL的root密碼忘記的解決方法
這篇文章主要介紹了阿里云Linux CentOS 7.2下自建MySQL的root密碼忘記的解決方法,需要的朋友可以參考下2017-07-07云服務(wù)器安裝mysql的實(shí)現(xiàn)步驟
在當(dāng)前的互聯(lián)網(wǎng)時(shí)代,云計(jì)算已經(jīng)成為重要的平臺(tái)支撐,本文就來介紹一下云服務(wù)器安裝mysql的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01MySQL [Warning] TIMESTAMP with implicit&
本文介紹了MySQL中常見的報(bào)錯(cuò)信息及其解決方法,主要包括TIMESTAMP with implicit DEFAULT value is deprecated、ERROR_FOR_DIVISION_BY_ZERO和NO_ZERO_DATE/NO_ZERO_IN_DATE等報(bào)錯(cuò)信息,以及對(duì)應(yīng)的配置文件設(shè)置和sql_mode修改方法,感興趣的朋友一起看看吧2025-02-02MySQL中CONCAT()函數(shù)拼接出現(xiàn)NULL的問題解決
本文主要介紹了MySQL中CONCAT()函數(shù)拼接出現(xiàn)NULL的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03