在 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.40 節,「複製和變數」。對於例外情況,請參閱第 7.4.4.3 節,「混合二進制日誌格式」。
可載入函數。 由於我們無法控制可載入函數的行為,我們必須假設它正在執行不安全的語句。
全文檢索外掛程式。 此外掛程式在不同的 MySQL 伺服器上可能會有所不同;因此,依賴它的語句可能會產生不同的結果。因此,在 MySQL 中,所有依賴全文檢索外掛程式的語句都被視為不安全。
觸發器或儲存程式更新具有 AUTO_INCREMENT 欄位的資料表。 這是因為在來源和副本上更新列的順序可能會不同,所以不安全。
此外,對具有包含
AUTO_INCREMENT
欄位 (此欄位不是此複合鍵的第一個欄位) 的複合主鍵的資料表進行INSERT
是不安全的。更多資訊,請參閱第 19.5.1.1 節,「複製和 AUTO_INCREMENT」。
在具有多個主鍵或唯一索引鍵的資料表上執行 INSERT ... ON DUPLICATE KEY UPDATE 語句。 當針對包含多個主鍵或唯一索引鍵的資料表執行時,此語句被視為不安全,因為它對儲存引擎檢查索引鍵的順序很敏感,而順序是不確定的,且 MySQL 伺服器更新的列選擇也取決於此順序。
針對具有多個唯一索引鍵或主鍵的資料表執行的
INSERT ... ON DUPLICATE KEY UPDATE
語句會被標記為基於語句的複製不安全。(錯誤 #11765650,錯誤 #58637)使用 LIMIT 進行更新。 擷取列的順序未指定,因此被視為不安全。請參閱第 19.5.1.19 節,「複製和 LIMIT」。
存取或參考日誌資料表。 系統日誌資料表的內容在來源和副本之間可能會有所不同。
交易操作後的非交易操作。 在交易中,允許任何非交易讀取或寫入在任何交易讀取或寫入之後執行被視為不安全。
更多資訊,請參閱第 19.5.1.36 節,「複製和交易」。
存取或參考自我記錄資料表。 所有對自我記錄資料表的讀取和寫入都被視為不安全。在交易中,任何在讀取或寫入自我記錄資料表之後的語句也被視為不安全。
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 節,「複製功能和問題」。