6.7 MySQL 事務(wù)與鎖定命令
蕉嶺ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!
6.7.1 BEGIN/COMMIT/ROLLBACK 句法
缺省的,MySQL 運(yùn)行在 autocommit 模式。這就意味著,當(dāng)你執(zhí)行完一個(gè)更新時(shí),MySQL 將立刻將更新存儲(chǔ)到磁盤上。
如果你使用事務(wù)安全表 (例如 InnoDB、BDB),通過下面的命令,你可以設(shè)置 MySQL 為非 autocommit 模式:
SET AUTOCOMMIT=0
在此之后,你必須使用 COMMIT 來存儲(chǔ)你的更改到磁盤上,或者使用 ROLLBACK ,如果你希望忽略從你的事務(wù)開始所做的更改。
如果你希望為一系列語句從 AUTOCOMMIT 模式轉(zhuǎn)換,你可以使用 START TRANSACTION 或 BEGIN 或 BEGIN WORK 語句:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;
START TRANSACTION 在 MySQL 4.0.11 中被加入;這是被推薦的開始一個(gè)特別(ad-hoc)事務(wù)的方式,因?yàn)檫@是 ANSI SQL 句法。
注意,如果你使用的是一個(gè)非事務(wù)安全表,更改會(huì)立刻被存儲(chǔ),不受 autocommit 模式狀態(tài)的約束。
當(dāng)你更新了一個(gè)非事務(wù)表后,如果你執(zhí)行一個(gè) ROLLBACK,你將得到一個(gè)錯(cuò)誤 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作為一個(gè)警告。所有事務(wù)安全表將被恢復(fù),但是非事務(wù)安全表將不會(huì)改變。
如果你使用 START TRANSACTION 或 SET AUTOCOMMIT=0,你應(yīng)該使用 MySQL
二進(jìn)制日志做備份以代替老的更新日志。事務(wù)處理被以一個(gè)大塊形式存儲(chǔ)在二進(jìn)制日志中,在 COMMIT
上面,為了保護(hù)回滾的事務(wù),而不是被存儲(chǔ)的。查看章節(jié) 4.9.4 二進(jìn)制日志。 如果您使用起動(dòng)事務(wù)處理或集AUTOCOMMIT=0
,您應(yīng)該使用MySQL 二進(jìn)制日志為備份代替更舊的更新日志。 事務(wù)處理存儲(chǔ)在二進(jìn)制登錄一大塊,做,保證, 滾的事務(wù)處理不存儲(chǔ)。 參見部分4
。9.4 二進(jìn)制日志。
下列命令自動(dòng)的結(jié)束一個(gè)事務(wù) (就好像你在執(zhí)行這個(gè)命令之前,做了一個(gè) COMMIT):
命令 命令 命令
ALTER TABLE BEGIN CREATE INDEX
DROP DATABASE DROP TABLE RENAME TABLE
TRUNCATE
你可以使用 SET TRANSACTION ISOLATION LEVEL ... 改變事務(wù)的隔離級(jí)。查看章節(jié) 6.7.3 SET TRANSACTION 句法。
6.7.2 LOCK TABLES/UNLOCK TABLES 句法
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES
LOCK TABLES 為當(dāng)前線程鎖定表。UNLOCK TABLES 釋放當(dāng)前線程擁有的所有鎖定。當(dāng)線程發(fā)出另一個(gè) LOCK TABLES,或當(dāng)與服務(wù)器的連接被關(guān)閉時(shí),被當(dāng)前線程鎖定的所有表將被自動(dòng)地解鎖。
為了在 MySQL 4.0.2 使用 LOCK TABLES ,你必須擁有一個(gè)全局的 LOCK TABLES 權(quán)限和一個(gè)在相關(guān)表上的
SELECT 權(quán)限。在 MySQL 3.23 中,你對該表需要有 SELECT、insert、DELETE 和 UPDATE 權(quán)限。
使用 LOCK TABLES 的主要原因是,仿效事務(wù)處理或在更新表時(shí)得到更快的速度。此后會(huì)有更詳細(xì)的描述。
如果一個(gè)線程在一個(gè)表上得到一個(gè) READ 鎖,該線程 (和所有其它線程) 只能從表中讀取。如果一個(gè)線程在一個(gè)表上得到一個(gè) WRITE 鎖,那么只有擁有這個(gè)鎖的線程可以從表中讀取和寫表。其它的線程被阻塞。
READ LOCAL 和 READ 之間的不同就在于,當(dāng)鎖被加載時(shí),READ LOCAL 允許非沖突(non-conflicting) INSERT 語句執(zhí)行。如果當(dāng)你加載著鎖時(shí)從 MySQL 外部操作數(shù)據(jù)庫文件,這將仍不能被使用。
當(dāng)你使用 LOCK TABLES 是地,你必須鎖定所有你將使用的表,并且必須使用與你的查詢中將使用的別名相同!如果你在一個(gè)查詢中多次使用一個(gè)表(用別名),你必須為每一個(gè)別名獲得一個(gè)鎖。
WRITE 鎖通過比 READ 鎖有更高的權(quán)限,以確保更新被盡快地處理。這就意味著,如果一個(gè)線程獲得一個(gè) READ
鎖,而同時(shí)另外一個(gè)線程請求一個(gè) WRITE 鎖,并發(fā)的 READ 鎖請求將等待直到 WRITE 線程得到了鎖并釋放了它。你可以使用
LOW_PRIORITY WRITE 鎖,當(dāng)該線程在等待 WRITE 鎖時(shí),它將允許其它的線程獲得 READ 鎖。 你應(yīng)該只使用
LOW_PRIORITY WRITE 鎖,如果你確信這將是最后一次,當(dāng)沒有線程將擁有 READ 鎖。
LOCK TABLES 工作如下:
以內(nèi)部定義的次序排序所有被鎖定的表 (從用戶立場說,該次序是不明確的)。
如果一個(gè)表被以一個(gè)讀鎖和一個(gè)寫鎖鎖定,將寫鎖放在讀鎖之前。
一次只鎖定一個(gè)表,只到線程得到所有的鎖定。
這個(gè)方案是為了確保,表鎖定死鎖釋放。 對于這個(gè)模式你仍然有些其它事情需要知道:
如果你對一個(gè)表使用一個(gè) LOW_PRIORITY WRITE 鎖定,這就意味著,MySQL 將等待這個(gè)鎖,直到?jīng)]有線程請求一個(gè) READ
鎖。當(dāng)線程得到了 WRITE 鎖,并等待獲得鎖定表列表中的下一個(gè)表的鎖定時(shí),其它所有的線程將等待 WRITE
鎖被釋放。如果這在你的應(yīng)用程序中會(huì)引起一個(gè)嚴(yán)重的問題,你應(yīng)該考慮將你的某些表轉(zhuǎn)換為事務(wù)安全表。
你可以使用 KILL 安全地殺死一個(gè)正在表鎖定的線程。查看章節(jié) 4.5.5 KILL 句法。
注意,你不應(yīng)該 鎖定你正在對其使用 INSERT DELAYED 的表。這是因?yàn)椋谶@種情況下,INSERT 是通過單獨(dú)的線程完成的。
通常,你不需要鎖定任何表,因?yàn)樗袉?UPDATE 語句都是原子的;其它的線程無法干擾當(dāng)前執(zhí)行的 SQL 語句。當(dāng)你無論如何希望鎖定表時(shí),這里有一些情況:
如果你在一束表上運(yùn)行許多操作,鎖定你將要使用的表,這會(huì)更快一些。當(dāng)然有不利的方面,其它線程將不能更新一個(gè) READ
鎖的表,并且沒有其它線程要以讀取一個(gè) WRITE 鎖的表。 在 LOCK TABLES 下,某些事運(yùn)行得更快一些的原因是,MySQL
將不會(huì)轉(zhuǎn)儲(chǔ)清除被鎖定表鍵高速緩沖,直到 UNLOCK TABLES 被調(diào)用 (通常鍵高速緩沖在每個(gè) SQL 語句后都會(huì)被轉(zhuǎn)儲(chǔ)清除)。這將加速在
MyISAM 表上的插入、更新、刪除。
如果你在 MySQL 中正在使用一個(gè)不支持事務(wù)的存儲(chǔ)引擎,如果你希望能確保沒有其它的線程會(huì)出現(xiàn)在一個(gè) SELECT 和 一個(gè) UPDATE 之間,你必須使用 LOCK TABLES 。下面的示例顯示為了安全地執(zhí)行,這里需要LOCK TABLES :
mysql LOCK TABLES trans READ, customer WRITE;
mysql SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql UPDATE customer SET total_value=sum_from_previous_statement
- WHERE customer_id=some_id;
mysql UNLOCK TABLES;
不使用 LOCK TABLES,將可能發(fā)生在 SELECT 和 UPDATE 語句執(zhí)行期間有另外一個(gè)線程可能在 trans 表中插入一行新記錄。
通過使用遞增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() 函數(shù),你可以在很多情況下避免使用 LOCK TABLES。
你也可以使用用戶級(jí)鎖定函數(shù) GET_LOCK() 和 RELEASE_LOCK() 解決一些情況,這些鎖被保存在服務(wù)器上的一個(gè)哈希表中,并以
pthread_mutex_lock() 和 pthread_mutex_unlock() 實(shí)現(xiàn)以獲得高速度。查看章節(jié) 6.3.6.2
輔助功能函數(shù)。
查看章節(jié) 5.3.1 MySQL 如何鎖定表,以獲取關(guān)于鎖定方案的更多信息。
你可以使用 FLUSH TABLES WITH READ LOCK 命令以讀鎖鎖定所有數(shù)據(jù)庫中的所有表。查看章節(jié) 4.5.3 FLUSH 句法。如果你有一個(gè)可以及時(shí)建立文件快照的文件系統(tǒng),例如 Veritas,這將是得到備份的非常方便方式。
注意:LOCK TABLES 不是事務(wù)安全的,在嘗試鎖定一個(gè)表之前,將自動(dòng)地提交所有的活動(dòng)事務(wù)。
6.7.3 SET TRANSACTION 句法
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
設(shè)置全局的、整個(gè)會(huì)話或下一個(gè)事務(wù)的事務(wù)隔離級(jí)。
缺省行為是設(shè)置下一個(gè)(未啟動(dòng)的)事務(wù)的隔離級(jí)。如果你使用 GLOBAL
關(guān)鍵詞,語句為所有在那個(gè)點(diǎn)上建立的新連接設(shè)置默認(rèn)的全局事務(wù)隔離級(jí)。為了這樣做,你需要有 SUPER 權(quán)限。使用 SESSION
關(guān)鍵詞為當(dāng)前連接所有將來執(zhí)行的事務(wù)設(shè)置默認(rèn)的事務(wù)隔離級(jí)。
你可以使用 --transaction-isolation=... 為 mysqld 設(shè)置默認(rèn)的全局隔離級(jí)。查看章節(jié) 4.1.1 mysqld 命令行選項(xiàng)
MYSQL 事務(wù)處理主要有兩種方法
1、用 begin, rollback, commit 來實(shí)現(xiàn)
begin 或/ start transaction )開始一個(gè)事務(wù)
rollback 事務(wù)回滾
commit 事務(wù)確認(rèn)
2、直接用 SET 來改變 MySQL 的自動(dòng)提交模式:
set autocommit=0 禁止自動(dòng)提交
set autocommit=1 開啟自動(dòng)提交
1.不管 autocommit 是1還是0
start transaction 后,只有當(dāng) commit 數(shù)據(jù)才會(huì)生效, rollback 后就會(huì)回滾。
2、當(dāng) autocommit 為 0 時(shí)
不管有沒有 start transaction .
只有當(dāng) commit 數(shù)據(jù)才會(huì)生效, rollback 后就會(huì)回滾。
3、如果 autocommit 為1 ,并且沒有 start transaction .
調(diào)用 rollback 是沒有用的。因?yàn)槭聞?wù)已經(jīng)自動(dòng)提交了。
事務(wù)測試1
事務(wù)測試2
flag 相當(dāng)一定義這個(gè)保存點(diǎn)的名字
savepoint flag : savepoint 允許在事務(wù)中創(chuàng)建一個(gè)保存點(diǎn),一個(gè)事務(wù)中可以有多個(gè)savepoint ;
release savepoint flag :刪除一個(gè)事務(wù)的保存點(diǎn),當(dāng)沒有指定的保存點(diǎn)時(shí),執(zhí)行該語句會(huì)拋出一個(gè)異常;
rollback to flag :把事務(wù)回滾到標(biāo)記點(diǎn);
set transaction :用來設(shè)置事務(wù)的隔離級(jí)別。InnoDB存儲(chǔ)引擎提供事務(wù)的隔離級(jí)別有
READ UNCOMMITTED 、 READ COMMITTED 、 REPEATABLE READ 和 SERIALIZABLE
select @@transaction_isolation;
SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only;
MySQL 事務(wù)
什么是事務(wù)?
MySQL 事務(wù)主要用于處理操作量大,復(fù)雜度高的數(shù)據(jù)。比如說,在人員管理系統(tǒng)中,你刪除一個(gè)人員,你既需要?jiǎng)h除人員的基本資料,也要?jiǎng)h除和該人員相關(guān)的信息,如信箱,文章等等,這樣,這些數(shù)據(jù)庫操作語句就構(gòu)成一個(gè)事務(wù)!
在 MySQL 中只有使用了 Innodb 數(shù)據(jù)庫引擎的數(shù)據(jù)庫或表才支持事務(wù)。
事務(wù)處理可以用來維護(hù)數(shù)據(jù)庫的完整性,保證成批的 SQL 語句要么全部執(zhí)行,要么全部不執(zhí)行。
事務(wù)用來管理 insert,update,delete 語句
一般來說,事務(wù)是必須滿足4個(gè)條件(ACID):原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨(dú)立性)、持久性(Durability)。
原子性:一個(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í)對其數(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é)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失。
在 MySQL 命令行的默認(rèn)設(shè)置下,事務(wù)都是自動(dòng)提交的,即執(zhí)行 SQL 語句后就會(huì)馬上執(zhí)行 COMMIT 操作。因此要顯式地開啟一個(gè)事務(wù)務(wù)須使用命令 BEGIN 或 START TRANSACTION,或者執(zhí)行命令 SET AUTOCOMMIT=0,用來禁止使用當(dāng)前會(huì)話的自動(dòng)提交。
from 樹懶學(xué)堂 - 一站式數(shù)據(jù)知識(shí)平臺(tái)
幾個(gè)步驟:
登陸ATM機(jī),輸入密碼;
連接數(shù)據(jù)庫,驗(yàn)證密碼;
驗(yàn)證成功,獲得用戶信息,比如存款余額等;
用戶輸入需要取款的金額,按下確認(rèn)鍵;
從后臺(tái)數(shù)據(jù)庫中減掉用戶賬戶上的對應(yīng)金額;
ATM吐出錢;
用戶把錢拿走。