MySQL 複寫中陳述式的「安全」是指該陳述式及其效果是否可以使用基於陳述式的格式正確複寫。如果陳述式是這樣,我們將該陳述式稱為安全;否則,我們將其稱為不安全。
一般而言,如果陳述式具有決定性,則為安全,如果不具決定性,則為不安全。但是,某些不具決定性的函式不被視為不安全(請參閱本節稍後的不被視為不安全的不具決定性函式)。此外,使用來自浮點數學函式(與硬體相關)的結果的陳述式一律被視為不安全(請參閱第 19.5.1.12 節「複寫和浮點數值」)。
安全與不安全陳述式的處理方式。陳述式的處理方式不同,取決於該陳述式是否被視為安全,以及二進位日誌格式(也就是說,binlog_format
的目前值)。
使用基於列的記錄時,不會區分安全與不安全陳述式的處理方式。
使用混合格式記錄時,標示為不安全的陳述式會使用基於列的格式記錄;視為安全的陳述式會使用基於陳述式的格式記錄。
使用基於陳述式的記錄時,標示為不安全的陳述式會產生此效果的警告。安全的陳述式會正常記錄。
每個被標記為不安全的語句都會產生警告。如果在來源端執行大量此類語句,可能會導致錯誤日誌檔案過大。為了防止這種情況,MySQL 具有警告抑制機制。如果在任何 50 秒的時間段內,最近的 50 個 ER_BINLOG_UNSAFE_STATEMENT
警告被產生超過 50 次,則會啟用警告抑制。啟用後,此類警告不會寫入錯誤日誌;相反地,每 50 個此類警告,會將一個註釋 The last warning was repeated
寫入錯誤日誌。只要最近的 50 個此類警告是在 50 秒或更短的時間內發出,此機制就會持續運作;一旦速率降低到此閾值以下,警告將再次正常記錄。警告抑制不會影響基於語句記錄方式的語句安全性判斷,也不會影響警告傳送到用戶端的方式。MySQL 用戶端仍然會針對每個此類語句收到一個警告。N
times in last S
seconds
更多資訊,請參閱第 19.2.1 節,「複製格式」。
包含系統函數的語句,這些函數在副本上可能傳回不同的值。 這些函數包括
FOUND_ROWS()
、GET_LOCK()
、IS_FREE_LOCK()
、IS_USED_LOCK()
、LOAD_FILE()
、RAND()
、RELEASE_LOCK()
、ROW_COUNT()
、SESSION_USER()
、SLEEP()
、SOURCE_POS_WAIT()
、SYSDATE()
、SYSTEM_USER()
、USER()
、UUID()
和UUID_SHORT()
。不被視為不確定的函數。 雖然這些函數不是確定性的,但為了記錄和複製的目的,它們被視為安全:
CONNECTION_ID()
、CURDATE()
、CURRENT_DATE()
、CURRENT_TIME()
、CURRENT_TIMESTAMP()
、CURTIME()
、LAST_INSERT_ID()
、LOCALTIME()
、LOCALTIMESTAMP()
、NOW()
、UNIX_TIMESTAMP()
、UTC_DATE()
、UTC_TIME()
和UTC_TIMESTAMP()
。更多資訊,請參閱第 19.5.1.14 節,「複製與系統函數」。
對系統變數的參照。 大多數系統變數無法使用基於語句的格式正確複製。請參閱第 19.5.1.39 節,「複製與變數」。關於例外情況,請參閱第 7.4.4.3 節,「混合二進位日誌格式」。
可載入函數。 由於我們無法控制可載入函數的行為,我們必須假設它正在執行不安全的語句。
全文搜尋外掛程式。 此外掛程式在不同的 MySQL 伺服器上可能表現不同;因此,依賴它的語句可能會產生不同的結果。因此,在 MySQL 中,所有依賴全文搜尋外掛程式的語句都被視為不安全。
觸發程序或儲存程序更新具有 AUTO_INCREMENT 欄位的資料表。 由於在來源端和副本上更新資料列的順序可能不同,因此這是不安全的。
此外,若
INSERT
插入的資料表其複合主鍵包含一個AUTO_INCREMENT
欄位,且該欄位不是此複合主鍵的第一個欄位,則該操作是不安全的。更多資訊,請參閱第 19.5.1.1 節,「複製與 AUTO_INCREMENT」。
在具有多個主鍵或唯一鍵的資料表上執行 INSERT ... ON DUPLICATE KEY UPDATE 語句。 當針對包含多個主鍵或唯一鍵的資料表執行時,此語句被視為不安全,因為它對儲存引擎檢查鍵的順序很敏感,而這是不確定的,MySQL 伺服器所選擇更新的資料列也取決於此。
針對具有多個唯一鍵或主鍵的資料表執行的
INSERT ... ON DUPLICATE KEY UPDATE
語句,會被標記為不安全,不適用於基於語句的複製。(Bug #11765650, Bug #58637)使用 LIMIT 的更新。 由於擷取資料列的順序未指定,因此被認為是不安全。請參閱第 19.5.1.18 節,「複製與 LIMIT」。
存取或參照日誌資料表。 來源端和副本端的系統日誌資料表內容可能不同。
交易操作之後的非交易操作。 在交易中,允許任何非交易讀取或寫入在任何交易讀取或寫入之後執行,都被視為不安全。
更多資訊,請參閱第 19.5.1.35 節,「複製與交易」。
存取或參照自我記錄資料表。 對自我記錄資料表的所有讀取和寫入都被視為不安全。在交易中,任何在讀取或寫入自我記錄資料表之後的語句也被視為不安全。
LOAD DATA 語句。
LOAD DATA
被視為不安全,當binlog_format=MIXED
時,該語句會以基於列的格式記錄。當binlog_format=STATEMENT
時,LOAD DATA
不會產生警告,這與其他不安全語句不同。XA 交易。 如果在來源端平行提交的兩個 XA 交易,在副本上以相反的順序準備,則可能發生鎖定相依性,而基於語句的複製無法安全解決此問題,而且複製有可能在副本上因死鎖而失敗。當設定
binlog_format=STATEMENT
時,XA 交易內的 DML 語句會被標記為不安全並產生警告。當設定binlog_format=MIXED
或binlog_format=ROW
時,XA 交易內的 DML 語句會使用基於列的複製記錄,因此不存在潛在的問題。參照非確定性函數的
DEFAULT
子句。 如果表達式預設值參照非確定性函數,則任何導致評估該表達式的語句對於基於語句的複製都是不安全的。這包括諸如INSERT
、UPDATE
和ALTER TABLE
等語句。與大多數其他不安全語句不同,此類語句無法以基於列的格式安全地複製。當binlog_format
設定為STATEMENT
時,該語句會被記錄並執行,但會將警告訊息寫入錯誤日誌。當binlog_format
設定為MIXED
或ROW
時,該語句不會被執行,並將錯誤訊息寫入錯誤日誌。有關明確預設值處理的更多資訊,請參閱明確預設值處理。
更多資訊,請參閱第 19.5.1 節,「複製功能與問題」。