MyDumper “喜歡” 觸發器麼?

是的,但現在它更“喜歡”它們,原因如下。

file

介紹

使用 LIKE 子句過濾特定表中的觸發器或視圖很常見。但是,它可能會欺騙您,特別是如果您看不到輸出(即在非交互式會話中)。讓我們看一個簡單的例子,以及如何以更可靠的方式處理任務。還有一個指向 mydumper 錯誤的額外鏈接,該錯誤是根據本實驗室的調查而修復的。是的,但現在它更喜歡它們,原因如下。

實驗室

首先,我們將創建兩個只有一個無符號整數列的虛擬表。該列也將是兩個表的主鍵。

CREATE TABLE `test_lab` (
`id` int unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `test2lab` (
`id` int unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

我們還將創建第三個表,它將作爲我們的“日誌”來跟蹤前兩個表中所做的插入。我們將在這裏使用複合主鍵(表名稱和 ID)。

CREATE TABLE `log_lab` (
`changed_table` varchar(50) NOT NULL,
`id` int unsigned NOT NULL,
PRIMARY KEY (`changed_table`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

現在,讓我們爲每個表添加一個觸發器。兩個表的觸發器相同,並將記錄複製到日誌表。

DELIMITER //

CREATE TRIGGER `test_lab_trigger_INS` AFTER INSERT ON `test_lab`

FOR EACH ROW BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test_lab', NEW.id) ;
END
//

CREATE TRIGGER `test2lab_trigger_INS` AFTER INSERT ON `test2lab`

FOR EACH ROW BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test2lab', NEW.id) ;
END
//
DELIMITER ;

最後,讓我們檢查一下我們是否正確完成了所有操作:

mysql> insert into `test_lab` values (8) ;
Query OK, 1 row affected (0.00 sec)

mysql> insert into `test2lab` values (2) ;
Query OK, 1 row affected (0.01 sec)

mysql> select * from log_lab ;
+---------------+----+
| changed_table | id |
+---------------+----+
| test_lab      |  8 |
| test2lab      |  2 |
+---------------+----+
2 rows in set (0.00 sec)

現在,我們已準備好運行我們爲其創建實驗室的測試用例。讓我們從使用這個語句開始:

mysql> SHOW TRIGGERS LIKE 'test2lab';
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| test2lab_trigger_INS | INSERT | test2lab | BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test2lab', NEW.id) ;
END | AFTER | 2024-04-13 10:35:45.29 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | msandbox@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)

一張表,一個觸發器,一行。都可以。

這次,我們將使用其他表名稱:

mysql> SHOW TRIGGERS LIKE 'test_lab' ;
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| test2lab_trigger_INS | INSERT | test2lab | BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test2lab', NEW.id) ;
END | AFTER | 2024-04-13 10:35:45.29 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | msandbox@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci |
| test_lab_trigger_INS | INSERT | test_lab | BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test_lab', NEW.id) ;
END | AFTER | 2024-04-13 10:35:45.29 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | msandbox@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
2 rows in set (0.00 sec)

人們可能會驚訝地看到兩個表都有兩行及其觸發器,但這是預期的行爲。 LIKE 語句不會根據模式執行嚴格的比較和過濾。您仍然可以在其中使用通配符 (%),它可以用來代替搜索字符串中任意數量的字符。在 LIKE 語句中使用佔位符 (_) 來匹配任何單個字符的情況不太常見。諷刺的是,我們使用佔位符匹配表名稱中的“_”和“2”字符。

在文章的開頭,我承諾展示一種更可靠的方法來處理該任務,所以這裏是:

mysql> SHOW TRIGGERS WHERE `Table` = 'test2lab';
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| test2lab_trigger_INS | INSERT | test2lab | BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test2lab', NEW.id) ;
END | AFTER | 2024-04-13 10:35:45.29 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | msandbox@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
1 row in set (0.01 sec)

mysql> SHOW TRIGGERS WHERE `Table` = 'test_lab';
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
| test_lab_trigger_INS | INSERT | test_lab | BEGIN
INSERT INTO log_lab (`changed_table`,`id`) VALUES ('test_lab', NEW.id) ;
END | AFTER | 2024-04-13 10:35:45.29 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | msandbox@localhost | utf8mb4 | utf8mb4_0900_ai_ci | utf8mb4_0900_ai_ci |
+----------------------+--------+----------+------------------------------------------------------------------------------------+--------+------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)

您可以過濾輸出中的任何其他列,不限於表。不要忘記使用 Table,因爲它是 MySQL 中的保留字,如果不使用它們(以及大多數其他列名),您將無法逃脫。

如果您想做自己的實驗,我將留給讀者使用 VIEW 進行相同的測試。

題外話

這時,你可能會問這個極端案例與現實世界有什麼關係。當一個包含下劃線而另一個包含數字時,表名稱略有不同的情況並不常見。除了無法獲得您願意獲得的輸出之外,這也是 mydumper/myloader 中出現錯誤的原因,我在此報告:

https://github.com/mydumper/mydumper/issues/1418

Mydumper 將每個表的觸發器放入單獨的文件中,並使用 LIKE 語句導致屬於 test2lab 的觸發器最終出現在 test_lab 觸發器文件中。

結論

本文介紹了了解運算符如何在 LIKE 子句示例中精確執行的重要性、如何創建快速實驗室來測試命令的結果以確保結果,以及如何使用運算符替代 LIKE。

更多技術文章,請訪問:https://opensource.actionsky.com/

關於 SQLE

SQLE 是一款全方位的 SQL 質量管理平臺,覆蓋開發至生產環境的 SQL 審覈和管理。支持主流的開源、商業、國產數據庫,爲開發和運維提供流程自動化能力,提升上線效率,提高數據質量。

SQLE 獲取

類型 地址
版本庫 https://github.com/actiontech/sqle
文檔 https://actiontech.github.io/sqle-docs/
發佈信息 https://github.com/actiontech/sqle/releases
數據審覈插件開發文檔 https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章