【MySQL精通之路】SQL語句(3)-鎖和事務語句

目錄

1.START TRANSACTION、COMMIT和ROLLBACK語句

2.無法回滾的語句

3.導致隱含COMMIT的語句

4.SAVEPOINT、ROLLBACK TO SAVEPOINT和RELEASE SAVEPOINT語句

5.LOCK INSTANCE FOR BACKUP和UNLOCK INSTANCE語句

6.LOCK TABLE和UNLOCK TABLES語句

6.1 表鎖獲取

6.2 表鎖釋放

6.3 表鎖與事務的交互

6.4 表鎖和觸發器

6.5 表鎖的限制和條件

7.SET TRANSACTION語句

7.1 事務隔離級別

7.2 事務訪問模式

7.3 事務范圍特性

8.XA事務

8.1 XA事務SQL語句

8.2 XA事務狀態

8.3 XA事務的限制


1.START TRANSACTION、COMMIT和ROLLBACK語句

START TRANSACTION[transaction_characteristic [, transaction_characteristic] ...]transaction_characteristic: {WITH CONSISTENT SNAPSHOT| READ WRITE| READ ONLY
}BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET autocommit = {0 | 1}

這些語句提供對事務使用的控制:

START TRANSACTION或BEGIN啟動新事務。

COMMIT提交當前事務,使其修改成為永久性的。

ROLLBACK回滾當前事務,取消其修改改。

SET自動提交禁用或啟用當前會話的默認自動提交模式。

默認情況下,MySQL在啟用自動提交模式的情況下運行。這意味著,當不在事務內部時,每個語句都是原子語句,就好像它被START TRANSACTIONCOMMIT包圍一樣。不能使用ROLLBACK撤消效果;但是,如果在語句執行過程中發生錯誤,則會回滾該語句。

要對單個語句系列隱式禁用自動提交模式,請使用START TRANSACTION語句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

使用START TRANSACTION時,在使用COMMIT或ROLLBACK結束事務之前,自動提交一直處于禁用狀態。然后,自動提交模式將恢復到以前的狀態。

START TRANSACTION允許使用多個修飾符來控制事務特性。要指定多個修飾符,請用逗號分隔。

WITH CONSISTENT SNAPSHOT修飾符為具有此功能的存儲引擎啟動一致讀取(快照讀)。

這僅適用于InnoDB。其效果與從任何InnoDB表中發出START TRANSACTION后接SELECT相同。(因為Innodb默認可重復讀隔離級別)

參見“一致無鎖讀取”。

WITH CONSISTENT SNAPSHOT修飾符不會更改當前事務隔離級別,因此只有當當前隔離級別允許一致讀取時,它才能提供一致的快照。

唯一允許一致讀的隔離級別是可重復讀取。對于所有其他隔離級別,WITH CONSISTENT SNAPSHOT子句將被忽略。忽略WITH CONSISTENT SNAPSHOT子句時會生成警告。

READ WRITEREAD ONLY修飾符設置事務訪問模式。處于事務中時,它們允許或禁止更改使用中的表。

READ ONLY限制防止一個事務修改或鎖定其他事務可見的存在事務的表或非事務表;事務仍然可以修改或鎖定臨時表。

當事務為只讀時,MySQL可以對InnoDB表上的查詢進行額外的優化。指定READ ONLY可確保在無法自動確定只讀狀態的情況下應用這些優化。

有關更多信息,請參閱“優化InnoDB只讀事務”。

如果未指定訪問模式,則應用默認模式。除非默認值已更改,否則它是讀/寫的。不允許在同一語句中同時指定READ WRITEREAD ONLY

在只讀模式下,仍然可以使用DML語句更改使用TEMPORARY關鍵字創建的表。不允許使用DDL語句進行更改,就像使用永久表一樣。

有關事務訪問模式的其他信息,包括更改默認模式的方法,請參閱“SET transaction語句”。

如果啟用了READ ONLY系統變量,則使用START TRANSACTION READ WRITE顯式啟動事務需要CONNECTION_ADMIN權限(或不推薦使用的SUPER權限)。

重要:

許多用于編寫MySQL客戶端應用程序(如JDBC)的API都提供了自己的啟動事務的方法,這些方法可以(有時也應該)用來代替從客戶端發送START TRANSACTION語句。

有關更多信息,請參閱“連接器和API”或API文檔。

要顯式禁用自動提交模式,請使用以下語句:

SET autocommit=0;

通過將autocommit設置為零禁用自動提交模式后,對事務安全表(如InnoDB或NDB的表)的更改不會立即永久化。您必須使用COMMIT將更改存儲到磁盤,或者使用ROLLBACK忽略更改。

autocommit是一個會話變量,必須為每個會話設置。

要為每個新連接禁用自動提交模式,請參閱“服務器系統變量”中對自動提交系統變量的描述。

支持將BEGINBEGIN WORK作為START TRANSACTION的別名來啟動事務。

START TRANSACTION是標準的SQL語法,是啟動特別事務的推薦方式,并且允許BEGIN不允許的修飾符。

BEGIN語句不同于BEGIN ... END用法。后者不啟動事務。參見BEGIN…END復合語句。

注意:

在所有存儲程序(存儲過程和函數、觸發器和事件)中,解析器將BEGIN[WORK]視為?BEGIN ... END。在此上下文中使用?START TRANSACTION開始事務。

COMMITROLLBACK以及CHAINRELEASE子句都支持可選的WORK關鍵字CHAINRELEASE可用于對事務完成進行額外控制。completion_type系統變量的值決定了默認的完成行為。

請參閱“服務器系統變量”。

AND CHAIN子句使新事務在當前事務結束后立即開始,并且新事務與剛剛終止的事務具有相同的隔離級別。

新事務還使用與剛剛終止的事務相同的訪問模式(READ WRITEREAD ONLY)。

RELEASE子句導致服務器在終止當前事務后斷開當前客戶端會話的連接。包含NO關鍵字會抑制CHAIN或RELEASE完成,如果completion_type系統變量默認設置為導致鏈接或發布完成,則這可能很有用。

開始事務會導致提交任何掛起的事務。有關更多信息,請參閱“導致隱性承諾的聲明”。

開始事務也會導致使用LOCK TABLES獲取的表鎖被釋放,就好像您已經執行了UNLOCK TABLES。開始事務不會釋放使用?FLUSH TABLES WITH READ LOCK.獲取的全局讀取鎖。

為了獲得最佳結果,應僅使用由單個事務安全存儲引擎管理的表來執行事務。否則,可能會出現以下問題:

如果您使用多個事務安全存儲引擎(如InnoDB)中的表,并且事務隔離級別不是SERIALIZABLE,那么當一個事務提交時,使用相同表的另一個正在進行的事務可能只看到第一個事務所做的一些更改。也就是說,混合引擎不能保證事務的原子性,可能會導致不一致。(如果混合引擎事務很少發生,則可以根據需要使用SET TRANSACTION ISOLATION LEVEL按每個事務將隔離級別設置為SERIALIZABLE。)

如果在事務中使用不安全的表,則無論自動提交模式的狀態如何,對這些表的更改都會立即存儲。

如果在更新事務中的非事務表后發出ROLLBACK語句,則會出現ER_WARNING_NOT_COMPLETE_ROLLBACK警告。將回滾對事務安全表的更改,但不會回滾對非事務安全表所做的更改。

COMMIT時,每個事務都存儲在Binlog日志中的一個塊中。

不會記錄已回滾的事務。(例外:對非事務表的修改無法回滾。如果回滾的事務包括對非事務表格的修改,則會在最后使用ROLLBACK語句記錄整個事務,以確保復制對非事務圖表的修改。)

請參閱“Binlog日志”。

您可以使用SET TRANSACTION語句更改事務的隔離級別或訪問模式。

參見“SET TRANSACTION語句”。

回滾可能是一個緩慢的操作,在用戶沒有明確要求的情況下(例如,當發生錯誤時),它可能會隱式發生。因此,SHOW PROCESSLIST在會話的State列中顯示Rolling back,不僅用于使用ROLLBACK語句執行的顯式回滾,還用于隱式回滾。

注意:

在MySQL 8.0中,BEGIN、COMMITROLLBACK不受--replicate do db--replicat ignore db rules的影響。

當InnoDB執行事務的完全回滾時,事務設置的所有鎖都會被釋放。如果事務中的單個SQL語句由于錯誤(如重復密鑰錯誤)而回滾,則在事務保持活動狀態時,將保留該語句設置的鎖。

之所以會發生這種情況,是因為InnoDB以這樣一種格式存儲行鎖,使得它以后無法知道哪個鎖是由哪個語句設置的。

如果事務中的SELECT語句調用存儲函數,而存儲函數中的語句失敗,則該語句將回滾。如果隨后對事務執行ROLLBACK,則整個事務將回滾。

2.無法回滾的語句

????????某些語句無法回滾。通常,這些語句包括數據定義語言(DDL)語句,例如創建刪除數據庫的語句,創建、刪除或更改表或存儲例程的語句。

????????您應該將交易設計為不包含此類報表。如果在事務的早期發出一個無法回滾的語句,而隨后另一個語句失敗,則在這種情況下,無法通過發出ROLLBACK語句來回滾事務的全部效果。


3.導致隱含COMMIT的語句

????????本節中列出的語句(以及它們的任何同義詞)隱式地結束當前會話中的任何活動事務,就好像您在執行該語句之前完成了COMMIT一樣。

這些語句中的大多數還會在執行后導致隱式提交。其目的是在其自己的特殊交易中處理每個此類聲明。事務控制和鎖定語句是例外:如果一個隱式提交發生在執行之前,另一個則不會發生在執行之后。


定義或修改數據庫對象的數據定義語言(DDL)語句:

ALTER EVENT, ALTER FUNCTION, ALTER PROCEDURE, ALTER SERVER, ALTER TABLE, ALTER TABLESPACE, ALTER VIEW, CREATE DATABASE, CREATE EVENT, CREATE FUNCTION, CREATE INDEX, CREATE PROCEDURE, CREATE ROLE, CREATE SERVER, CREATE SPATIAL REFERENCE SYSTEM, CREATE TABLE, CREATE TABLESPACE, CREATE TRIGGER, CREATE VIEW, DROP DATABASE, DROP EVENT, DROP FUNCTION, DROP INDEX, DROP PROCEDURE, DROP ROLE, DROP SERVER, DROP SPATIAL REFERENCE SYSTEM, DROP TABLE, DROP TABLESPACE, DROP TRIGGER, DROP VIEW, INSTALL PLUGIN, RENAME TABLE, TRUNCATE TABLE, UNINSTALL PLUGIN.

如果使用了TEMPORARY關鍵字CREATE TABLEDROP TABLE語句不會提交事務。(這不適用于對臨時表的其他操作,如ALTER TABLECREATE INDEX,它們確實會導致提交。)但是,盡管沒有發生隱式提交,但語句也不能回滾,這意味著使用此類語句會違反事務原子性。

例如,如果使用CREATE TEMPORARY TABLE,然后回滾事務,則該表仍然存在。
InnoDB中的CREATE TABLE語句作為單個事務處理。

這意味著用戶的ROLLBACK不會撤消用戶在該事務期間所做的CREATE TABLE語句
CREATE TABLE ... SELECT創建非臨時表時,SELECT會在執行語句之前和之后導致隱式提交。(CREATE TEMPORARY TABLE…SELECT沒有發生提交。)


隱式使用或修改mysql數據庫中的表的語句:ALTER USER, CREATE USER, DROP USER, GRANT, RENAME USER, REVOKE, SET PASSWORD.


事務控制和鎖定語句BEGIN,LOCK TABLES,SET autocommit=1(如果值還不是1),START TRANSACTION,UNLOCK TABLES。

UNLOCK TABLES僅在當前任何表已被LOCK TABLS鎖定以獲取非事務表鎖的情況下提交事務。在FLUSH TABLES WITH READ LOCK之后,UNLOCK TABLES不會發生提交,因為后者的語句不會獲取表級鎖

事務不能嵌套。這是在發出START TRANSACTION 語句或其同義詞之一時對任何當前事務執行隱式提交的結果。

XA事務處于ACTIVE狀態時,不能在該事務中使用導致隱式提交的語句。

BEGIN語句不同于啟動BEGIN ... END復合語句。后者不會導致隱式提交

參見“BEGIN…END復合語句”。


數據加載語句:加載數據。LOAD DATA導致僅對使用NDB存儲引擎的表進行隱式提交。


管理聲明:ANALYZE TABLE, CACHE INDEX, CHECK TABLE, FLUSH, LOAD INDEX INTO CACHE, OPTIMIZE TABLE, REPAIR TABLE, RESET (but not RESET PERSIST).


復制控制語句:START REPLICA, STOP REPLICA, RESET REPLICA, CHANGE REPLICATION SOURCE TO,CHANGE MASTER TO

在MySQL 8.0.22中,SLAVE關鍵字REPLICA替換。


4.SAVEPOINT、ROLLBACK TO SAVEPOINT和RELEASE SAVEPOINT語句

SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier

InnoDB支持SQL語句SAVEPOINT、ROLLBACK TO SAVEPOINTRELEASE SAVEPONTROLLBACK的可選WORK關鍵字

SAVEPOINT語句設置名稱為identifier的命名事務保存點。

如果當前事務具有相同名稱的保存點,則會刪除舊的保存點并設置新的保存點。

ROLLBACK TO SAVEPOINT語句將事務回滾到命名的保存點,而不終止事務。

當前事務在設置保存點后對行所做的修改將在回滾中撤消,但InnoDB不會釋放保存點后存儲在內存中的行鎖。(對于新插入的行,鎖定信息由存儲在該行中的事務ID攜帶;該鎖不會單獨存儲在內存中。在這種情況下,行鎖將在撤消中釋放。)在命名存儲點之后設置的存儲點將被刪除。

如果ROLLBACK TO SAVEPOINT語句返回以下錯誤,則表示不存在具有指定名稱的存儲點:

ERROR 1305 (42000): SAVEPOINT identifier does not exist

InnoDB支持SQLRELEASE SAVEPOINT語句從當前事務的一組存儲點中刪除命名的存儲點。不會發生提交或回滾。如果保存點不存在,則為錯誤。

如果執行COMMIT或不命名保存點的ROLLBACK,則會刪除當前事務的所有保存點。

當調用存儲函數或激活觸發器時,會創建一個新的保存點級別。以前級別上的存儲點不可用,因此不會與新級別上的保存點沖突。當函數或觸發器終止時,它創建的任何存儲點都將被釋放,并恢復以前的存儲點級別。

5.LOCK INSTANCE FOR BACKUP和UNLOCK INSTANCE語句

LOCK INSTANCE FOR BACKUPUNLOCK INSTANCE

LOCK INSTANCE FOR BACKUP獲取一個實例級備份鎖,該鎖允許在聯機備份期間使用DML,同時防止可能導致快照不一致的操作。

執行LOCK INSTANCE FOR BACKUP語句需要BACKUP_ADMIN權限

從早期版本就地升級到MySQL 8.0時,BACKUP_ADMIN權限會自動授予具有RELOAD權限的用戶。

多個會話可以同時持有一個備份鎖。

UNLOCK INSTANCE釋放當前會話持有的備份鎖。如果會話終止,會話所持有的備份鎖也會被釋放。

LOCK INSTANCE FOR BACKUP可防止創建、重命名或刪除文件。REPAIR TABLE TRUNCATE TABLEOPTIMIZE TABLE和帳戶管理語句被阻止。

參見“賬戶管理語句”。

修改未記錄在InnoDB redolog日志中的InnoDB文件的操作也被阻止。

LOCK INSTANCE FOR BACKUP允許只影響用戶創建的臨時表的DDL操作。

實際上,屬于用戶創建的臨時表的文件可以在保留備份鎖的同時創建重命名刪除。還允許創建binlog日志文件。

LOCK INSTANCE FOR BACKUP語句對實例有效時,不應發出PURGE BINARY LOGS,因為它從服務器中刪除文件違反了備份鎖的規則。在MySQL 8.0.28中,這是不允許的。

lock INSTANCE FOR backup獲取的備份鎖獨立于事務鎖和FLUSH TABLES tbl_name[,tbl_name]獲取的鎖。。。WITH READ LOCK,并且允許以下語句序列:

LOCK INSTANCE FOR BACKUP;
FLUSH TABLES tbl_name [, tbl_name] ... WITH READ LOCK;
UNLOCK TABLES;
UNLOCK INSTANCE;
FLUSH TABLES tbl_name [, tbl_name] ... WITH READ LOCK;
LOCK INSTANCE FOR BACKUP;
UNLOCK INSTANCE;
UNLOCK TABLES;

lock_wait_timeout設置定義了LOCK INSTANCE FOR BACKUP 語句在放棄之前等待獲取鎖的時間量。

6.LOCK TABLE和UNLOCK TABLES語句

LOCK {TABLE | TABLES}tbl_name [[AS] alias] lock_type[, tbl_name [[AS] alias] lock_type] ...lock_type: {READ [LOCAL]| [LOW_PRIORITY] WRITE
}UNLOCK {TABLE | TABLES}

MySQL允許客戶端會話顯式地獲取表鎖,以便與其他會話合作訪問表,或者防止其他會話在會話需要獨占訪問表時修改表。會話只能為自己獲取或釋放鎖。一個會話無法獲取另一個會話的鎖,也無法釋放另一會話持有的鎖。

鎖可以用來模擬事務,或者在更新表時提高速度。這在表鎖定限制和條件中有更詳細的解釋。

LOCK TABLES顯式獲取當前客戶端會話的表鎖。可以為基表或視圖獲取表鎖。您必須具有LOCK TABLES權限,以及要鎖定的每個對象的SELECT權限。

對于視圖鎖定,LOCK TABLES將視圖中使用的所有基表添加到要鎖定的表集中,并自動鎖定它們。對于任何被鎖定的視圖的基礎表,LOCK tables檢查視圖定義器(對于SQL SECURITY definer視圖)或調用程序(對于所有視圖)是否對這些表具有適當的權限。

如果使用lock TABLES顯式鎖定表,則觸發器中使用的任何表也將隱式鎖定,如lock TABLES和觸發器中所述。

如果使用lock TABLES顯式鎖定表,則會隱式打開和鎖定與外鍵約束相關的任何表。對于外鍵檢查,對相關表采用共享只讀鎖(lock TABLES read)。對于級聯更新,在操作中涉及的相關表上采用共享的無寫鎖(lock TABLES write)。

UNLOCK TABLES顯式釋放當前會話持有的任何表鎖。LOCK TABLES在獲取新鎖之前隱式釋放當前會話持有的任何表鎖。

UNLOCK TABLES的另一個用途是釋放通過FLUSH TABLES with read lock語句獲取的全局讀取鎖,該語句使您能夠鎖定所有數據庫中的所有表。參見第15.7.8.3節“FLUSH聲明”。(如果您有像Veritas這樣可以及時獲取快照的文件系統,這是一種非常方便的獲取備份的方法。)

LOCK TABLE是LOCK TABLES的同義詞;UNLOCK TABLE是UNLOCK TABLES的同義詞。

表鎖只防止其他會話進行不適當的讀取或寫入。持有WRITE鎖的會話可以執行表級操作,如DROP table或TRUNCATE table。對于持有READ鎖的會話,不允許執行DROP TABLE和TRUNCATE TABLE操作。

以下討論僅適用于非臨時表。對于TEMPORARY表,允許(但忽略)LOCK TABLES。創建該表的會話可以自由訪問該表,而不考慮其他可能生效的鎖定。不需要鎖,因為沒有其他會話可以看到該表。

6.1 表鎖獲取

要在當前會話中獲取表鎖,請使用LOCK TABLES語句,該語句將獲取元數據鎖

(請參閱“元數據鎖定”)。

以下鎖類型可用:

READ[LOCAL]鎖:

持有鎖的會話可以讀取表(但不能寫入表)。

多個會話可以同時獲取表的READ鎖。

其他會話可以讀取該表,而無需顯式獲取READ鎖。

LOCAL修飾符允許其他會話在持有鎖時執行不沖突的INSERT語句(并發插入)。

(請參閱“并發插入”。)

但是,如果您要在持有鎖的情況下使用服務器外部的進程來操作數據庫,則不能使用READ LOCAL。對于InnoDB表,READ LOCAL與READ相同。

[LOW_PRIORITY]寫鎖:

持有鎖的會話可以讀取寫入表。

只有持有鎖的會話才能訪問該表。在解除鎖定之前,任何其他會話都無法訪問它。

持有WRITE鎖時,其他會話對表的鎖定請求會被阻止。

LOW_PRIORITY修改器沒有效果。在MySQL的早期版本中,它影響了鎖定行為,但現在已經不是這樣了。它現在已被棄用,使用它會產生警告。請改用不帶LOW_PRIORITY的WRITE。

寫鎖通常比讀鎖具有更高的優先級,以確保盡快處理更新。

這意味著,如果一個會話獲得了READ鎖,然后另一個會話請求了WRITE鎖,則隨后的READ鎖請求將等待,直到請求WRITE鎖定的會話獲得了鎖并釋放了它。

對于?max_write_lock_count系統變量的小值,可能會出現此策略的例外;

請參閱“元數據鎖定”。

如果LOCK TABLES語句由于任何表上的其他會話持有鎖而必須等待,則它會阻塞,直到可以獲取所有鎖為止。

需要鎖的會話必須在單個LOCKTABLES語句中獲取所需的所有鎖。當這樣獲得的鎖被持有時,會話只能訪問被鎖定的表。例如,在以下語句序列中,由于t2未在LOCK TABLES語句中鎖定,因此嘗試訪問t2時出錯:

mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
|        3 |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES

INFORMATION_SCHEMA數據庫中的表是一個例外。即使會話持有通過LOCK TABLES獲得的表鎖,也可以在不顯式鎖定的情況下訪問它們。

不能在使用相同名稱的單個查詢中多次引用鎖定的表。請改用別名,并為表和每個別名獲取一個單獨的鎖:(無法重入)

mysql> LOCK TABLE t WRITE, t AS t1 READ;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;

第一次INSERT發生錯誤,因為鎖定表有兩個對同一名稱的引用。第二次INSERT成功,因為對表的引用使用了不同的名稱。

如果語句通過別名引用表,則必須使用相同的別名鎖定該表。在不指定別名的情況下鎖定表是不起作用的:

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

相反,如果使用別名鎖定表,則必須使用該別名在語句中引用該表:

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

6.2 表鎖釋放

當會話持有的表鎖被釋放時,它們都會同時被釋放。會話可以顯式釋放其鎖,也可以在特定條件下隱式釋放鎖。

會話可以使用UNLOCK TABLES顯式釋放鎖。

如果會話在已經持有鎖的情況下發出LOCK TABLES語句來獲取鎖,則在授予新鎖之前,它的現有鎖將被隱式釋放。

如果會話開始一個事務(例如,使用START TRANSACTION),則會執行一個隱式的UNLOCK TABLES,從而釋放現有的鎖。(有關表鎖定和事務之間的交互的更多信息,請參閱表鎖定與事務的交互。)

如果客戶端會話的連接終止,無論是正常還是異常,服務器都會隱式釋放會話持有的所有表鎖(事務性和非事務性)。如果客戶端重新連接,鎖定將不再有效。

此外,如果客戶端有一個活動事務,則服務器會在斷開連接時回滾該事務,如果發生重新連接,則新會話將以啟用自動提交的方式開始。

因此,客戶端可能希望禁用自動重新連接。在自動重新連接生效的情況下,如果發生重新連接,但丟失了任何表鎖或當前事務,則不會通知客戶端。

在禁用自動重新連接的情況下,如果連接斷開,則發出的下一條語句將出錯。

客戶端可以檢測到錯誤并采取適當的操作,例如重新獲取鎖或重做事務。請參閱自動重新連接控制。

注意:

????????如果對鎖定的表使用ALTER TABLE,則該表可能會變為解鎖表。例如,如果您嘗試第二次ALTER TABLE操作,結果可能是出現錯誤。表“tbl_name”未使用LOCK TABLES鎖定。要處理此問題,請在進行第二次更改之前再次鎖定表。另請參閱第“ALTER TABLE的問題”。

6.3 表鎖與事務的交互

LOCK TABLEUNLOCK TABLES與事務的使用交互如下:

LOCK TABLES不是事務安全的,并且在嘗試鎖定表之前隱式提交任何活動事務。

UNLOCK TABLES隱式提交任何活動事務,但前提是已使用LOCK TABLES 獲取表鎖。例如,在以下一組語句中,UNLOCK TABLES釋放全局讀鎖,但不提交事務,因為沒有有效的表鎖:

FLUSH TABLES WITH READ LOCK;
START TRANSACTION;
SELECT ... ;
UNLOCK TABLES;

開始事務(例如,使用START TRANSACTION)隱式提交任何當前事務并釋放現有的表鎖。

FLUSH TABLES WITH READ LOCK獲取全局讀取鎖,而不是表鎖,因此在表鎖定和隱式提交方面,它不受與LOCK TABLES和UNLOCK table相同的行為的影響

例如,START TRANSACTION不會釋放全局讀取鎖。

參見“FLUSH聲明”。

其他隱式導致事務被提交的語句不會釋放現有的表鎖

有關此類聲明的列表,請參閱“導致隱式提交的語句”。

對事務表(如InnoDB表)使用LOCKTABLESUNLOCK TABLES的正確方法是,以SET autocommit=0(而不是START transaction)開頭,后跟LOCKTABLes開始事務,并且在顯式提交事務之前不調用UNLOCK TABLES。例如,如果您需要寫入表t1并從表t2讀取,則可以執行以下操作:

SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;

?當您調用LOCK TABLES時,InnoDB在內部獲取自己的表鎖,MySQL獲取自己的表鎖。InnoDB在下一次提交時釋放其內部表鎖,但MySQL要釋放其表鎖,必須調用UNLOCK TABLES。

您不應該讓autocommit=1,因為InnoDB在調用LOCK TABLES后立即釋放其內部表鎖,死鎖很容易發生。

如果autocommit=1,InnoDB根本不獲取內部表鎖,以幫助舊應用程序避免不必要的死鎖。

ROLLBACK不會釋放表鎖。

6.4 表鎖和觸發器

如果使用LOCK TABLES顯式鎖定表,則觸發器中使用的任何表也會隱式鎖定:

這些鎖與使用LOCK TABLES語句顯式獲取的鎖在同一時間獲取。

觸發器中使用的表的鎖取決于該表是否僅用于讀取。如果是這樣,一個讀鎖就足夠了。否則,將使用寫鎖。

如果表被顯式鎖定以使用LOCK TABLES進行讀取,但由于可能在觸發器內進行修改而需要鎖定以進行寫入,則會使用寫鎖而不是讀鎖。(也就是說,由于表在觸發器中的出現而需要的隱式寫鎖會導致表的顯式讀鎖請求轉換為寫鎖請求。)

假設您使用以下語句鎖定兩個表t1和t2:

LOCK TABLES t1 WRITE, t2 READ;

如果t1或t2具有任何觸發器,則觸發器內使用的表也被鎖定。假設t1具有這樣定義的觸發器:

CREATE TRIGGER t1_a_ins AFTER INSERT ON t1 FOR EACH ROW
BEGINUPDATE t4 SET count = count+1WHERE id = NEW.id AND EXISTS (SELECT a FROM t3);INSERT INTO t2 VALUES(1, 2);
END;

LOCK TABLES語句的結果是,t1和t2被鎖定是因為它們出現在語句中,t3和t4被鎖定是由于它們在觸發器中使用:

t1被鎖定用于根據WRITE鎖請求進行寫入。

t2被鎖定以進行寫入,即使該請求是針對READ鎖定。這是因為t2被插入到觸發器中,所以READ請求被轉換為WRITE請求。

t3被鎖用于讀取,因為它僅從觸發器內讀取。

t4被鎖用于寫入,因為它可能在觸發器內被更新。

6.5 表鎖的限制和條件

您可以安全地使用KILL來終止正在等待表鎖的會話。參見“KILL語句”。

在存儲的程序中不能使用LOCK TABLES和UNLOCK TABLES。

performance_schema數據庫中的表不能用LOCK TABLES鎖定,setup_xxx表除外。

LOCK TABLES生成的鎖的作用域是一個MySQL服務器它與NDB Cluster不兼容,后者無法在mysqld的多個實例之間強制執行SQL級別的鎖

您可以改為在API應用程序中強制鎖定。

有關更多信息,請參閱“與多個NDB集群節點相關的限制”。

LOCK TABLES語句有效時禁止使用以下語句:CREATE TABLE、CREATE TABLE...LIKECREATE VIEW、DROP VIEWDDL語句

對于某些操作,必須訪問mysql數據庫中的系統表。

例如,HELP語句需要服務器端幫助表的內容,CONVERT_TZ()可能需要讀取時區表。

服務器會根據需要隱式鎖定系統表以進行讀取,因此不需要顯式鎖定它們。這些表按剛才所述進行處理:

mysql.help_category
mysql.help_keyword
mysql.help_relation
mysql.help_topic
mysql.time_zone
mysql.time_zone_leap_second
mysql.time_zone_name
mysql.time_zone_transition
mysql.time_zone_transition_type

如果要使用lock tables語句顯式地對這些表中的任何一個表放置WRITE鎖,則該表必須是唯一鎖定的表;任何其他表都不能用同一語句鎖定。

通常,您不需要鎖定表,因為所有單個UPDATE語句都是原子語句任何其他會話都不能干擾任何其他當前正在執行的SQL語句

然而,在一些情況下,鎖表可能會提供優勢:

如果要在一組MyISAM表上運行許多操作,鎖定要使用的表會快得多。
鎖定MyISAM表可以加快插入、更新或刪除這些表的速度,因為MySQL在調用UNLOCK tables之前不會刷新鎖定表的密鑰緩存。通常,在每條SQL語句之后都會刷新密鑰緩存。

鎖定表的缺點是,沒有會話可以更新READ鎖定的表(包括持有鎖的表),也沒有會話可以訪問WRITE鎖定的表格,而不是持有鎖的表格。

如果將表用于非事務存儲引擎,如果要確保SELECT和UPDATE之間沒有其他會話修改表,則必須使用LOCK tables。此處顯示的示例要求LOCK TABLES安全執行:

LOCK TABLES trans READ, customer WRITE;
SELECT SUM(value) FROM trans WHERE customer_id=some_id;
UPDATE customerSET total_value=sum_from_previous_statementWHERE customer_id=some_id;
UNLOCK TABLES;

如果沒有LOCK TABLES,另一個會話可能會在SELECT和UPDATE語句執行之間的trans表中插入新行。


在許多情況下,通過使用相對更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函數,可以避免使用LOCK TABLES

在某些情況下,您還可以通過使用用戶級咨詢鎖定函數GET_LOCK()和RELEASE_LOCK()來避免鎖定表。這些鎖保存在服務器中的哈希表中,并使用pthread_mutex_lock()和pthread_mutex_unlock()實現高速。

參見“鎖功能”。

有關鎖定策略的更多信息,請參閱“內部鎖定方法”。

7.SET TRANSACTION語句

SET [GLOBAL | SESSION] TRANSACTIONtransaction_characteristic [, transaction_characteristic] ...transaction_characteristic: {ISOLATION LEVEL level| access_mode
}level: {REPEATABLE READ| READ COMMITTED| READ UNCOMMITTED| SERIALIZABLE
}access_mode: {READ WRITE| READ ONLY
}

此語句指定事務特征。它采用一個由逗號分隔的一個或多個特征值的列表。每個特征值設置事務隔離級別或訪問模式。隔離級別用于InnoDB表上的操作。訪問模式指定事務是以讀/寫模式操作還是以只讀模式操作。

此外,SET TRANSACTION可以包括一個可選的GLOBAL或SESSION關鍵字來指示語句的范圍。

7.1 事務隔離級別

要設置事務隔離級別,請使用ISOLATION LEVEL級別子句。

不允許在同一SET TRANSACTION語句中指定多個ISOLATION LEVEL子句。

默認隔離級別為REPEATABLE READ。其他允許的值包括READ COMMITTEDREAD UNCOMITTEDSERIALIZABLE

有關這些隔離級別的信息,請參閱“事務隔離級別”。

7.2 事務訪問模式

要設置事務訪問模式,請使用READ WRITE或READ ONLY子句。不允許在同一SET TRANSACTION語句中指定多個訪問模式子句。

默認情況下,事務以讀/寫模式進行,允許對事務中使用的表進行讀和寫操作。可以使用訪問模式為READ WRITE的SET TRANSACTION顯式指定此模式。

如果事務訪問模式設置為只讀,則禁止更改表。這可能使存儲引擎能夠在不允許寫入時進行性能改進。

在只讀模式下,仍然可以使用DML語句更改使用TEMPORARY關鍵字創建的表。不允許使用DDL語句進行更改,就像使用永久表一樣。

還可以使用START transaction語句為單個事務指定READ WRITE和READ ONLY訪問模式。

7.3 事務范圍特性

您可以為當前會話或僅為下一個事務全局設置事務特性:

使用GLOBAL關鍵字:

該語句在全局范圍內適用于所有后續會話。

現有會話不受影響。

使用SESSION關鍵字:

該語句適用于當前會話中執行的所有后續事務。

事務中允許使用該語句,但不影響當前正在進行的事務。

如果在事務之間執行,則該語句將覆蓋設置命名特性的下一個事務值的任何先前語句。

沒有任何SESSION或GLOBAL關鍵字:

該語句僅適用于會話中執行的下一個單個事務。

后續事務將恢復為使用命名特性的會話值。

事務中不允許使用該語句:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ERROR 1568 (25001): Transaction characteristics can't be changed
while a transaction is in progress

?更改全局事務特性需要CONNECTION_ADMIN權限(或不推薦使用的SUPER權限)。任何會話都可以自由更改其會話特性(即使在事務的中間)或其下一個事務的特性(在該事務開始之前)。

要在服務器啟動時設置全局隔離級別,請在命令行或配置文件中使用--transaction isolation=level選項。此選項的級別值使用破折號而不是空格,因此允許的值為READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ或SERIALIZABLE。

類似地,要在服務器啟動時設置全局事務訪問模式,請使用--transaction只讀選項。默認值為OFF(讀/寫模式),但對于只讀模式,該值可以設置為ON。

例如,要將隔離級別設置為REPEATABLE READ,將訪問模式設置為READ WRITE,請在配置文件的[mysqld]部分使用以下行

[mysqld]
transaction-isolation = REPEATABLE-READ
transaction-read-only = OFF

在運行時,可以使用set transaction語句間接設置全局、會話和下一個事務范圍級別的特性,如前所述。也可以使用set語句直接設置它們,為transaction_inisolation和transaction_read_only系統變量賦值:

SET TRANSACTION允許可選的GLOBAL和SESSION關鍵字用于設置不同作用域級別的事務特性。

用于為transaction_inisolationtransaction_read_only系統變量賦值的SET語句具有用于在不同作用域級別設置這些變量的語法。

下表顯示了每個SET TRANSACTION變量賦值語法設置的特征作用域級別。

事務特性的SET TRANSACTION語法

語法事務影響的范圍
SET GLOBAL TRANSACTION transaction_characteristicGlobal
SET SESSION TRANSACTION transaction_characteristicSession
SET TRANSACTION transaction_characteristicNext transaction only

事務特征的SET語法

語法事務影響的范圍
SET GLOBAL var_name = valueGlobal
SET @@GLOBAL.var_name = valueGlobal
SET PERSIST var_name = valueGlobal
SET @@PERSIST.var_name = valueGlobal
SET PERSIST_ONLY var_name = valueNo runtime effect
SET @@PERSIST_ONLY.var_name = valueNo runtime effect
SET SESSION var_name = valueSession
SET @@SESSION.var_name = valueSession
SET var_name = valueSession
SET @@var_name = valueNext transaction only

可以在運行時檢查事務特征的全局值和會話值:

SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only;
SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only;

8.XA事務

InnoDB存儲引擎支持XA事務

MySQL XA實現基于X/Open CAE文檔分布式事務處理:XA規范。本文檔由The Open Group發布,可在http://www.opengroup.org/public/pubs/catalog/c193.htm “XA事務的限制”描述了當前XA實現的限制。

在客戶端,沒有特殊要求。MySQL服務器的XA接口由以XA關鍵字開頭的SQL語句組成。MySQL客戶端程序必須能夠發送SQL語句并理解XA語句接口的語義。它們不需要與最近的客戶端庫鏈接。舊的客戶端庫也可以使用。

在MySQL連接器中,MySQL連接器/J 5.0.0及更高版本通過一個為您處理XA SQL語句接口的類接口直接支持XA。

XA支持分布式事務,即允許多個獨立的事務資源參與全局事務的能力。事務性資源通常是RDBMS,但也可以是其他類型的資源。

全局事務涉及多個操作,這些操作本身是事務性的,但所有操作都必須作為一個組成功完成,或者作為一個小組回滾。

本質上,這將ACID屬性“向上”擴展,以便多個ACID事務可以作為具有ACID屬性的全局操作的組件一起執行。(與非分布式事務一樣,如果您的應用程序對讀取現象敏感,則可能首選SERIALIZABLE。可重復讀取可能不足以用于分布式事務。)

分布式事務的一些示例:

應用程序可以充當將消息服務與RDBMS相結合的集成工具。該應用程序確保處理消息發送、檢索和處理的事務(也涉及事務數據庫)都發生在全局事務中。您可以將其視為“事務性電子郵件”

應用程序執行涉及不同數據庫服務器的操作,如MySQL服務器和Oracle服務器(或多個MySQL服務器),其中涉及多個服務器的操作必須作為全局事務的一部分進行,而不是作為每個服務器本地的獨立事務進行。

銀行將賬戶信息保存在RDBMS中,并通過自動柜員機(ATM)分配和接收資金。有必要確保ATM操作正確地反映在帳戶中,但這不能單獨使用RDBMS來完成。全球交易管理器集成ATM和數據庫資源,以確保金融交易的整體一致性。

使用全局事務的應用程序涉及一個或多個資源管理器和一個事務管理器:

資源管理器(RM)提供對事務性資源的訪問。數據庫服務器是一種資源管理器。必須能夠提交或回滾RM管理的事務。

事務管理器(TM)協調作為全局事務一部分的事務。它與處理這些事務的RM進行通信。全局事務中的單個事務是全局事務的“分支”。全局事務及其分支通過稍后描述的命名方案來標識。

XA的MySQL實現使MySQL服務器能夠充當資源管理器,在全局事務中處理XA事務。連接到MySQL服務器的客戶端程序充當事務管理器。

要執行全局事務,必須知道涉及哪些組件,并使每個組件達到可以提交或回滾的程度。根據每個組件報告的成功能力,它們都必須作為一個原子組進行提交或回滾。也就是說,要么所有的組件都必須提交,要么所有組件都必須回滾。要管理全局事務,必須考慮到任何組件或連接網絡可能出現故障。

執行全局事務的過程使用兩階段提交(2PC)。這發生在全局事務的分支執行的操作之后。

在第一階段,準備好所有分支。也就是說,TM告訴他們做好承諾的準備。通常,這意味著管理分支的每個RM都會在穩定的存儲中記錄該分支的操作。分支指示它們是否能夠做到這一點,并且這些結果用于第二階段。

在第二階段,TM告訴RM是提交還是回滾。如果所有分支在準備好時都表示能夠提交,則會告知所有分支進行提交。如果任何分支在準備時表示無法提交,則會通知所有分支回滾。

在某些情況下,全局事務可能使用單階段提交(1PC)。例如,當事務管理器發現全局事務僅由一個事務資源(即單個分支)組成時,可以告知該資源同時準備和提交。

8.1 XA事務SQL語句

要在MySQL中執行XA事務,請使用以下語句:

XA {START|BEGIN} xid [JOIN|RESUME]XA END xid [SUSPEND [FOR MIGRATE]]XA PREPARE xidXA COMMIT xid [ONE PHASE]XA ROLLBACK xidXA RECOVER [CONVERT XID]

對于XA START,JOIN和RESUME子句是可識別的,但不起作用。

對于XA END,SUSPEND[For MIGRATE]子句已被識別,但無效。

每個XA語句都以XA關鍵字開頭,其中大多數語句都需要一個xid值。xid是XA事務標識符。它指示語句應用于哪個事務。xid值由客戶端提供,或由MySQL服務器生成。xid值由一到三部分組成:

xid: gtrid [, bqual [, formatID ]]

gtrid是全局事務標識符,bqual是分支限定符,formatID是標識gtrid和bqual值使用的格式的數字。如語法所示,bqual和formatID是可選的。如果未給定,則默認bqual值為“”。如果未給定,則默認的formatID值為1。

gtrid和bqual必須是字符串文字,每個文字的長度最多為64字節(而不是字符)。gtrid和bqual可以通過多種方式指定。您可以使用帶引號的字符串('ab')、十六進制字符串(X'6162'、0x6162)或位值(b'nnn')。

formatID是一個無符號整數。

gtrid和bqual值由MySQL服務器的底層XA支持例程以字節為單位進行解釋。但是,在解析包含XA語句的SQL語句時,服務器使用一些特定的字符集。為了安全起見,將gtrid和bqual寫成十六進制字符串。

xid值通常由事務管理器生成。一個TM生成的值必須與其他TM生成的數值不同。給定的TM必須能夠識別XA RECOVER語句返回的值列表中自己的xid值。

XA START xid使用給定的xid值啟動XA事務。每個XA事務都必須有一個唯一的xid值,因此該值當前不能被另一個XA事務使用。使用gtrid和bqual值來評估唯一性。XA事務的所有以下XA語句都必須使用與XA START語句中給定的相同的xid值來指定。如果使用這些語句中的任何一個,但指定的xid值與某些現有XA事務不對應,則會發生錯誤。

從MySQL 8.0.31開始,當服務器使用--replicate do db或--replicade ignore db運行時,默認數據庫不會過濾XA START、XA BEGIN、XA END、XA COMMIT和XA ROLLBACK語句。

一個或多個XA事務可以是同一全局事務的一部分。給定全局事務中的所有XA事務都必須在xid值中使用相同的gtrid值。因此,gtrid值必須是全局唯一的,這樣給定的XA事務是哪個全局事務的一部分就不會有歧義。對于全局事務中的每個XA事務,xid值的bqual部分必須不同。(bqual值不同的要求是當前MySQL XA實現的限制。它不是XA規范的一部分。)

XA RECOVER語句返回MySQL服務器上處于PREPARED狀態的XA事務的信息。(請參閱第15.3.8.2節“XA事務狀態”。)無論是哪個客戶端啟動的,輸出都包括服務器上每個這樣的XA事務的一行。

XA RECOVER需要XA_RECOVER_ADMIN權限。此特權要求防止用戶發現未完成的已準備XA事務的XID值,而不是自己的事務。它不會影響XA事務的正常提交或回滾,因為啟動它的用戶知道它的XID。

XA RECOVER輸出行如下所示(例如xid值由部分“abc”、“def”和7組成):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
|        7 |            3 |            3 | abcdef |
+----------+--------------+--------------+--------+

?輸出列具有以下含義:

formatID是事務xidformatID部分

gtrid_lengthxidgtrid部分的長度(以字節為單位)

bqual_lengthxidbqual部分的長度(以字節為單位)

數據是xidgtridbqual部分的串聯

XID值可能包含不可打印的字符。XA RECOVER允許使用可選的CONVERT XID子句,以便客戶端可以請求十六進制的XID值。

8.2 XA事務狀態

XA事務通過以下狀態進行:

1.使用XA START啟動XA事務并將其置于ACTIVE狀態

2.對于ACTIVE XA事務,發出組成該事務的SQL語句,然后發出XA END語句。XA END將事務置于IDLE狀態

3.對于IDLE XA事務,您可以發出XA PREPARE語句或XA COMMIT ... ONE PHASE 語句:

XA PREPARE將事務置于PREPARED狀態

此時,XA RECOVER語句在其輸出中包括事務的xid值,因為XA RECOVERE列出了所有處于PREPARED狀態的XA事務。

XA COMMIT ... ONE PHASE 準備并提交事務。由于事務終止,XA RECOVER未列出xid值。

4.對于PREPARED XA事務,可以發出XA COMMIT語句來提交和終止事務,或者發出XA ROLLBACK來回滾和終止事務。


下面是一個簡單的XA事務,它將一行作為全局事務的一部分插入到表中:

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)

這里有一個簡單的XA事務,它將一行插入到表中,作為全局事務的一部分。

在MySQL 8.0.28及更早版本中,在給定客戶端連接的上下文中,XA事務和本地(非XA)事務是互斥的。

例如,如果發出XA START以開始XA事務,則在提交或回滾XA事務之前,無法啟動本地事務。相反,如果使用START ?TRANSACTION啟動了本地事務,則在事務提交或回滾之前,不能使用XA語句。

MySQL 8.0.29及更高版本支持分離的XA事務,由?xa_detach_on_prepare系統變量啟用(默認為on)。

在執行XA PREPARE之后,獨立的事務將與當前會話斷開連接(并且可以由另一個連接提交或回滾)。

這意味著當前會話可以自由啟動新的本地事務或XA事務,而不必等待準備好的XA事務被提交或回滾。

當XA事務被分離時,連接對其準備的任何XA事務都沒有特殊的了解。如果當前會話在另一個連接已經提交或回滾給定的XA事務(即使是它準備的事務)之后嘗試提交或回滾,則該嘗試將被拒絕,并出現無效的XID錯誤(ER_XAER_NOTA),因為請求的XID不再存在。行動

注意:

獨立的XA事務不能使用臨時表。

獨立的XA事務被禁用(?xa_detach_on_prepare設置為OFF)時,XA事務將保持連接,直到它被原始連接提交或回滾,如前面針對MySQL 8.0.28和更早版本所述。對于組復制中使用的MySQL服務器實例,不建議禁用獨立的的XA事務;有關詳細信息,請參閱服務器實例配置。

如果XA事務處于ACTIVE狀態,則不能發出任何導致隱式提交的語句。這將違反XA合約,因為您無法回滾XA事務。嘗試執行這樣的語句會引發以下錯誤:

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed
when global transaction is in the ACTIVE state

“導致隱性提交的語句”中列出了適用上述備注的聲明。

8.3 XA事務的限制

XA事務支持僅限于InnoDB存儲引擎。

對于“外部XA”,MySQL服務器充當資源管理器,客戶端程序充當事務管理器。

對于“內部XA”,MySQL服務器中的存儲引擎充當RM,服務器本身充當TM。

內部XA支持受到單個存儲引擎功能的限制。內部XA是處理涉及多個存儲引擎的XA事務所必需的。內部XA的實現要求存儲引擎支持表處理程序級別的兩階段提交,而目前這僅適用于InnoDB。

對于XA STARTJOINRESUME子句是可識別的,但不起作用

對于XA ENDSUSPEND[FOR MIGRATE]子句已被識別,但無效

對于全局事務中的每個XA事務,xid值的bqual部分都不同的要求是當前MySQL XA實現的限制。它不是XA規范的一部分。

XA事務分兩部分寫入binlog日志。

當發出XA PREPARE時,事務的第一部分直到XA PREPARE都是使用初始GTID寫入的。XA_prepare_log_event用于識別二進制日志中的此類事務。當發出XA COMMITXA ROLLBACK時,使用第二個GTID寫入事務的第二部分,該部分僅包含XA COMMIT或者XA ROLLBACK語句。請注意,事務的初始部分(由XA_prepare_log_event標識)后面不一定跟著它的XA COMMITXA ROLLBACK,這可能會導致任何兩個XA事務的交錯二進制日志記錄。XA事務的兩個部分甚至可以出現在不同的二進制日志文件中。這意味著PREPARED狀態下的XA事務現在是持久的,直到發出明確的XA COMMITXA ROLLBACK語句,確保XA事務與復制兼容。

在復制副本上,在XA事務準備好后,它立即與復制應用程序線程分離,并且可以由復制副本上的任何線程提交或回滾

這意味著同一個XA事務可以出現在events_transactions_current表中,不同線程上的狀態不同。events_transactions_current表顯示線程上最近監視的事務事件的當前狀態,并且在線程空閑時不更新此狀態。

因此,在XA事務被另一個線程處理后,它仍然可以在原始應用程序線程的PREPARED狀態下顯示。要確定仍處于PREPARED狀態并且需要恢復的XA事務,請使用XA RECOVER語句,而不是Performance Schema事務表

使用XA事務存在以下限制:

在MySQL 8.0.30之前,XA事務對于binlog日志的意外停止沒有完全的彈性。

如果在服務器執行XA PREPARE、XA COMMIT、XA ROLLBACKXA COMMITONE PHASE語句的過程中出現意外停止,服務器可能無法恢復到正確的狀態,從而使服務器和二進制日志處于不一致的狀態。

在這種情況下,binlog日志可能包含未應用的額外XA事務,或者未應用的XA事務。此外,如果啟用了GTID,恢復后@@GLOBAL.GTID_EXECUTED可能無法正確描述已應用的事務。請注意,如果在XA PREPARE之前、在XA PREPREPAREXA COMMIT(或XA ROLLBACK)之間或在XA COMMITXA ROLLBACK之后發生意外停止,則服務器和二進制日志將正確恢復保持一致狀態

從MySQL 8.0.30開始,這不再是一個問題;服務器將XA PREPARE實現為兩階段操作,它維護存儲引擎和服務器之間的準備操作的狀態,并在存儲引擎和二進制日志之間強制執行順序,以便在狀態在服務器節點上保持一致和持久之前不進行廣播。

您應該注意,當同一事務XID用于順序執行XA事務,并且在?XA COMMIT ... ONE PHASE處理過程中發生中斷時,可能無法再同步binlog日志和存儲引擎之間的狀態。

如果剛才描述的一系列事件發生在存儲引擎中準備好prepared該事務之后,而XA COMMIT語句仍在執行,則可能會發生這種情況。這是一個已知的問題。

不支持將復制篩選器binlog日志篩選器XA事務結合使用。

表的篩選可能會導致復制副本上的XA事務為空,并且不支持空的XA事務

此外,由于副本的連接元數據存儲庫應用程序元數據存儲庫存儲在InnoDB表中(在MySQL 8.0中成為默認值),數據引擎事務的內部狀態會在經過過濾的XA事務之后發生變化,并且可能與復制事務上下文狀態不一致。

每當XA事務受到復制篩選器的影響時,無論事務是否因此為空,都會記錄錯誤ER_XA_REPLICATION_FILTERS。

如果事務不為空,則復制副本可以繼續運行,但您應該采取措施停止對XA事務使用復制篩選器,以避免潛在的問題。如果事務為空,則復制副本將停止。在這種情況下,復制副本可能處于未確定的狀態,在這種狀態下,復制過程的一致性可能會受到損害。特別是,副本的副本上的gtid_executed集可能與源上的不一致。

要解決此問題,請隔離源并停止所有復制,然后檢查整個復制拓撲的GTID一致性。撤消生成錯誤消息的XA事務,然后重新啟動復制。

XA事務被認為對于基于語句的復制是不安全的。如果在源上并行提交的兩個XA事務在復制副本上以相反的順序準備,則可能會發生無法安全解決的鎖依賴關系,并且復制可能會失敗,導致復制副本出現死鎖。這種情況可能發生在單線程多線程復制副本上。

當設置binlog_format=STATION時,XA事務內的DML語句將發出警告。

當設置binlog_format=MIXEDbinlog_foormat=ROW時,XA事務中的DML語句使用基于行的復制進行記錄,并且不存在潛在問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15522.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15522.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15522.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

qemu+gdb調試linux內核

打開CONFIG_DEBUG_INFO,編譯內核 通過圖形菜單配置該宏,執行make menuconfig。 kernel hacking —> compile-time checks and compiler options —> compile the kernel with debug info 驗證是否打開成功,grep -nr “CONFIG_DEBUG_INFO” .config。 打開成功,然后…

plsql 學習

過程化編程語言 賦值:: ||:連接符號 dbms_output.put_line() :輸出的語句 var_name ACCOUNTLIBRARY.USERNAME%type; 變量名;某個表的數據類型;賦值給變量名 用下面的方法更好用 異常exception 循…

力扣HOT100 - 75. 顏色分類

解題思路&#xff1a; 單指針&#xff0c;對數組進行兩次遍歷。 class Solution {public void sortColors(int[] nums) {int p 0;int n nums.length;for (int i 0; i < n; i) {if (nums[i] 0) {int tmp nums[i];nums[i] nums[p];nums[p] tmp;p;}}for (int i p; i …

java庫和包的概念

在Java中&#xff0c;"庫"和"包"是兩個不同的概念&#xff0c;但它們之間存在著密切的關聯。 庫&#xff08;Library&#xff09; 定義&#xff1a;庫是一組已經編寫好的代碼和資源&#xff0c;用于解決特定的問題或提供特定的功能。它可以包含一個或多個…

【前端每日基礎】day19——回調函數

回調函數 回調函數是一種常見的編程概念&#xff0c;它是指在函數執行完畢后&#xff0c;將另一個函數作為參數傳遞給它&#xff0c;以便在特定條件滿足時調用這個函數。回調函數通常用于處理異步操作、事件處理、定時器等場景&#xff0c;以實現非阻塞式的程序設計。 特點和…

存儲+調優:存儲-IP-SAN-EXTENSION

存儲調優&#xff1a;存儲-IP-SAN-EXTENSION 文件系統的鎖標記 GFS&#xff08;鎖表空間&#xff09; ----------- ------------ ------------- 節點 | ndoe1 | | node2 | | node3 | ---------- ------…

斷更是我的錯

打算在暑假每天兩個文章&#xff0c;大概是6月20多號開始吧。

vue3中watch語法

在Vue 3中&#xff0c;watch仍然是一個用于觀察和響應Vue實例上的數據變化的選項。watch選項接受一個對象&#xff0c;該對象中的屬性對應要觀察的數據屬性&#xff0c;并指定對應的回調函數&#xff0c;用于處理數據變化時的邏輯。 watch選項的語法如下&#xff1a; watch: …

GNSS中的多路徑效應原理及計算方法

1 多路徑效應原理 圖1 多路徑效應原理圖 2 計算方法 如需原文&#xff0c;可加多源融合定位與智能控制討論群獲取,QQ群號&#xff1a;51885949

ORACLE 6節點組成的ACFS文件系統異常的分析思路

近期遇到多次6節點集群的ACFS文件系統環境異常問題&#xff1b;如24日中午12點附近出現ACFS文件系統訪問異常&#xff0c;通過查看集群ALERT日志、CSSD進程日志及OSW監控軟件的日志&#xff0c;可以發現OSW監控軟件在11:55-12:40分時沒有收集到虛擬機LINUX主機的監控數據&#…

【OceanBase診斷調優】—— 直連普通租戶時遇到報錯:Tenant not in this server

本文介紹了直連 OceanBase 數據庫中的普通租戶時&#xff0c;出現報錯&#xff1a;ERROR 5150 (HY000) : Tenant not in this server 的處理方法。 問題描述 在 n-n 或者 n-n-n (n>1) 的部署架構中&#xff0c;使用 2881 端口 直連 OceanBase 集群的普通租戶&#xff0c;可…

ChatGPT大語言模型發展歷史

技術背景與OpenAI成立 2010年代初&#xff1a;隨著深度學習技術的突破&#xff0c;特別是循環神經網絡(RNN)和長短時記憶網絡(LSTM)的成功應用&#xff0c;自然語言處理(NLP)領域開始經歷一場革命。2015年12月&#xff1a;OpenAI作為一個旨在確保人工智能(AI)研究造福全人類的…

Java并行流

Java并行流 什么是并行流&#xff1f;并行流的優缺點優點缺點 如何使用&#xff1f;1.創建流2.轉換為并行流3.流操作4.收集結果5.關閉流 并行流的本質1.任務劃分和調度2.并發處理數據3.任務結果合并4.性能優化 參考文獻官方文檔 什么是并行流&#xff1f; 并行流&#xff08;p…

【C++風云錄】揭秘醫療機器人:技術解析與應用探索

打造智能醫療&#xff1a;醫療機器人技術與手術輔助 前言 本文將在深度和廣度上探討六種尖端醫療機器人系統&#xff0c;并重點介紹其應用、C控制接口及其功能。這些機器人系統分別是ROSA Robot、Da Vinci Surgical SystemSDK、Intuitive Surgical’s da Vinci Xi、Medroboti…

黑龍江等保測評新要求下的政府信息化安全實踐案例分析

在數字化轉型的浪潮中&#xff0c;政府機構作為社會管理和公共服務的核心&#xff0c;其信息安全的重要性日益凸顯。近期&#xff0c;黑龍江省積極響應國家網絡安全戰略&#xff0c;依據最新的等級保護測評&#xff08;簡稱“等保測評”&#xff09;要求&#xff0c;對政府信息…

SpringBoot運維篇(打包,多環境,日志)

文章目錄 一、SpringBoot程序的打包與運行二、配置高級三、多環境開發四、日志 一、SpringBoot程序的打包與運行 剛開始做開發學習的小伙伴可能在有一個知識上面有錯誤的認知&#xff0c;我們天天寫程序是在Idea下寫的&#xff0c;運行也是在Idea下運行的。 ?但是實際開發完成…

CDH6.3.2集成Flink1.17

直接運行腳本即可&#xff0c;一鍵輸出相關依賴包 運行步驟已給到文檔 下載地址

Html基礎筆記

Html超文本標記語言 (HyperText Markup Language) 超文本 指的是網頁中可以顯示的內容(圖片,超鏈接,視頻,) 標記語言 標記–>標簽(標注) 例如:買東西的時候—>商品具有標簽,看到標簽就知道商品的屬性(價格,材質,型號等,) 標記語言就是提供了很多的標簽,不同的標簽…

若依框架對于后端返回異常后怎么處理?

1、后端返回自定義異常serviceException 2、觸發該異常后返回json數據 因為若依對請求和響應都封裝了&#xff0c;所以根據返回值response獲取不到Code值但若依提供了一個catch方法用來捕獲返回異常的數據 3、處理的方法

antd design 自定義表頭

<template><a-card :bordered"false"><div class"contentWrap"><!-- 查詢區域 --><div class"table-page-search-wrapper"><a-form layout"inline" keyup.enter.native"searchQuery">&…