器查看全攻略:從命令到權(quán)限與排障實(shí)踐)
做MySQL運(yùn)維和開發(fā)這些年我有個特別深的體會觸發(fā)器是數(shù)據(jù)庫里最容易被忽視、又最容易惹禍的東西。表結(jié)構(gòu)、索引、慢查詢都有人盯唯獨(dú)TRIGGERS經(jīng)常被晾在一邊。直到線上數(shù)據(jù)被莫名改動、某張表總是自動多出記錄、或者刪數(shù)據(jù)刪不掉才想起來要查查觸發(fā)器??烧娴搅艘榈臅r候很多人連SHOW TRIGGERS和information_schema.TRIGGERS都分不清更不用說8.0之后的一些細(xì)節(jié)變化。這篇文章就把“查看觸發(fā)器”這件事徹底講透。從最基礎(chǔ)的命令姿勢到權(quán)限坑、主從坑、字符集坑再到面試時人家到底想問什么我都會結(jié)合實(shí)操經(jīng)驗(yàn)一步步拆開說。不管你是剛接觸MySQL的開發(fā)新手還是經(jīng)常上生產(chǎn)環(huán)境排查問題的運(yùn)維這篇文章都能讓你少走彎路。哪怕你只是臨時接手一個別人的庫看完也能五秒鐘定位出這張表到底“背著”哪些觸發(fā)器、里面干了什么。1. 繞不開的問題觸發(fā)器到底為什么要“查看”1.1 觸發(fā)器是“隱形的代碼”先聊一個最基本的認(rèn)知觸發(fā)器Trigger是數(shù)據(jù)庫對象里的一種它綁定在某張表上當(dāng)表發(fā)生INSERT、UPDATE、DELETE操作時會被自動執(zhí)行一段SQL邏輯。聽起來很方便但它有個很陰險的屬性——它是隱形的。什么概念就是你給一張表做SELECT * FROM user看不到任何觸發(fā)器你做SHOW CREATE TABLE user默認(rèn)情況下也看不到和觸發(fā)器相關(guān)的信息。但實(shí)際插入一條數(shù)據(jù)的時候后臺可能已經(jīng)悄悄改了另一張表、寫了一條日志、更新了一個統(tǒng)計字段。很多時候你查數(shù)據(jù)發(fā)現(xiàn)對不上根本不是業(yè)務(wù)代碼的問題而是觸發(fā)器的“鍋”。所以我一直建議接手任何一套數(shù)據(jù)庫第一步不是看表結(jié)構(gòu)而是先把觸發(fā)器摸一遍。摸清楚了才知道這套庫的“隱藏邏輯”在哪才不會在后面排障的時候被它坑得體無完膚。1.2 查看別人的庫先從觸發(fā)器開始再說一個更實(shí)際的場景。很多開發(fā)同學(xué)在團(tuán)隊協(xié)作里會拿到一個“歷史悠久”的數(shù)據(jù)庫里面有幾十張表光看表結(jié)構(gòu)已經(jīng)夠累了可你還得知道里面有沒有觸發(fā)器。為什么因?yàn)橛|發(fā)器會直接影響你對業(yè)務(wù)邏輯的判斷。你在改一條UPDATE語句之前如果不清楚這張表上掛了一個AFTER UPDATE觸發(fā)器可能會忽略它同步到別的表的副作用。等你上線之后發(fā)現(xiàn)其他表的數(shù)據(jù)變了再回頭看已經(jīng)不是一句“回滾”能解決的。我自己就見過有人把一張大表的UPDATE操作做成了半小時級的長事務(wù)最后定位出來是因?yàn)橛|發(fā)器里套了一次全表操作直接把性能拖垮。所以查看觸發(fā)器不是“想起來了看一眼”的事而是數(shù)據(jù)庫變更、排障、審計流程里的一個前置步驟。理解了這一點(diǎn)再看下面的實(shí)操姿勢你才會明白為什么我要分門別類講得這么細(xì)。2. 查觸發(fā)器之前先把四種姿勢搞清楚查看MySQL觸發(fā)器本質(zhì)上有四類路徑分別適用于不同場景。我先把它們拉出來對比后面再逐一說透。查看方式核心命令/位置適用場景特點(diǎn)SHOW TRIGGERSSHOW TRIGGERS [FROM db] [LIKE pattern]快速查看當(dāng)前庫或指定庫所有觸發(fā)器輸出直觀字段聚合度好但有信息截斷風(fēng)險system schema查詢information_schema.TRIGGERS精確篩選、腳本化處理、按任意條件過濾字段最全可SQL過濾適合二次加工SHOW CREATE TRIGGERSHOW CREATE TRIGGER trigger_name查看單個觸發(fā)器的完整定義語句拿到重建腳本可完整復(fù)制客戶端可視化Navicat、MySQL Workbench等GUI日常人工排查直觀但操作效率較低不適合批量處理2.1 SHOW TRIGGERS最直觀但藏著小坑這是大家最常用的一條命令。語法很簡單SHOW TRIGGERS; SHOW TRIGGERS FROM mydb; SHOW TRIGGERS FROM mydb LIKE log%;不加任何條件的時候它列出當(dāng)前連接所在數(shù)據(jù)庫或者叫當(dāng)前schema的所有觸發(fā)器。如果當(dāng)前沒有選中任何庫有些客戶端版本會直接報No database selected。這一點(diǎn)注意一下就行。它的結(jié)果集有以下關(guān)鍵字段Trigger觸發(fā)器名字。Event觸發(fā)事件顯示為INSERT、UPDATE、DELETE。Table觸發(fā)器所在的表名。Statement觸發(fā)器執(zhí)行的邏輯主體。注意這里顯示的是轉(zhuǎn)換成文本之后的內(nèi)容如果SQL很長會被截斷默認(rèn)不是完整的。TimingBEFORE還是AFTER。Created創(chuàng)建時間。sql_mode創(chuàng)建觸發(fā)器時的SQL模式。Definer定義者格式通常是userhost。character_set_client、collation_connection、Database Collation字符集相關(guān)的三件套。這個命令的好處就是快一眼能看到全貌。但它的“坑”也很明顯Statement字段會被截斷長觸發(fā)器你在這根本看不到完整邏輯而且篩選能力弱只能按庫、按名字LIKE過濾沒辦法按表名過濾。比如我只想看orders表上的所有觸發(fā)器用SHOW TRIGGERS FROM mydb LIKE %orders%就只能碰運(yùn)氣了因?yàn)長IKE匹配的是觸發(fā)器名字不是表名。所以單獨(dú)依賴SHOW TRIGGERS查全量沒問題但定向排查、按表查詢你必須得用下面這種姿勢。2.2 information_schema.TRIGGERS最靈活批量篩選首選information_schema.TRIGGERS是MySQL官方提供的系統(tǒng)視圖專門存放觸發(fā)器的元數(shù)據(jù)。這里才是查觸發(fā)器的“正規(guī)軍”字段最全、支持任意過濾條件而且可以通過SQL方式批量處理。先看它的核心字段結(jié)構(gòu)DESC information_schema.TRIGGERS;重點(diǎn)字段說明TRIGGER_CATALOG固定為def了解一下即可。TRIGGER_SCHEMA觸發(fā)器所在的庫名。TRIGGER_NAME觸發(fā)器名稱。EVENT_MANIPULATION觸發(fā)事件類型INSERT、UPDATE、DELETE。EVENT_OBJECT_SCHEMA綁定的庫名。EVENT_OBJECT_TABLE綁定的表名。ACTION_ORDER同表同事件多個觸發(fā)器的執(zhí)行順序。ACTION_CONDITION觸發(fā)條件一般是NULL。ACTION_STATEMENT觸發(fā)器的完整執(zhí)行語句。ACTION_ORIENTATION一般是ROW行級觸發(fā)器。ACTION_TIMINGBEFORE或AFTER。ACTION_REFERENCE_OLD_TABLE、ACTION_REFERENCE_NEW_TABLE不影響行級觸發(fā)器通常NULL。ACTION_REFERENCE_OLD_ROW舊值引用通常為OLD。ACTION_REFERENCE_NEW_ROW新值引用通常為NEW。CREATED創(chuàng)建時間。SQL_MODE創(chuàng)建時的SQL模式。DEFINER定義者。CHARACTER_SET_CLIENT、COLLATION_CONNECTION、DATABASE_COLLATION字符集相關(guān)信息。為什么說它靈活因?yàn)槟憧梢噪S便查-- 查某張表上的所有觸發(fā)器 SELECT TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA mydb AND EVENT_OBJECT_TABLE orders; -- 查所有庫里名字帶log的觸發(fā)器 SELECT * FROM information_schema.TRIGGERS WHERE TRIGGER_NAME LIKE %log%; -- 查所有庫的AFTER INSERT觸發(fā)器數(shù)量 SELECT TRIGGER_SCHEMA, COUNT(*) AS cnt FROM information_schema.TRIGGERS WHERE EVENT_MANIPULATION INSERT AND ACTION_TIMING AFTER GROUP BY TRIGGER_SCHEMA;注意一點(diǎn)在MySQL 8.0中information_schema.TRIGGERS的字段還是這些沒有大的改動兼容性很好可以放心用。2.3 SHOW CREATE TRIGGER看定義拿重建腳本SHOW TRIGGERS和information_schema.TRIGGERS雖然能告訴你觸發(fā)器的基本信息和語句但如果你需要拿到一個可以直接重建的完整腳本就得用SHOW CREATE TRIGGER。SHOW CREATE TRIGGER mydb.trg_order_after_insert;執(zhí)行結(jié)果返回兩列Trigger觸發(fā)器名和SQL Original Statement完整創(chuàng)建語句。注意這里的SQL Original Statement左側(cè)會有一個Create Trigger字樣是用于重建的完整DDL定義可以直接復(fù)制出來作為備份或者遷移腳本。這里我一般會配合!的快捷方式在mysql客戶端里查看排版避免一行超長語句看不清楚。當(dāng)然在DBeaver、DataGrip這類工具里可以直接格式化顯示體驗(yàn)會好很多。除此之外還可以用SHOW CREATE TABLE看觸發(fā)器的存在性。執(zhí)行SHOW CREATE TABLE orders\G在輸出內(nèi)容的最后面會有TRIGGERS部分但注意它只列出觸發(fā)器名字和事件不會展示完整定義所以不要指望它能替代SHOW CREATE TRRIGER。2.4 圖形客戶端不提工單也能“可視化”看開發(fā)環(huán)境里我最常用的還是Navicat。操作路徑很簡單打開連接展開目標(biāo)庫找到“觸發(fā)器”文件夾雙擊即可看到庫內(nèi)所有觸發(fā)器列表。點(diǎn)某個觸發(fā)器右側(cè)會出現(xiàn)兩部分上半部分是屬性定義者、時間、事件、表名下半部分是定義SQL。還可以直接右鍵“修改觸發(fā)器”查看完整代碼或者“復(fù)制SQL”拿到重建語句。MySQL Workbench的路徑也類似在左側(cè)的SCHEMAS面板里展開庫找Tables下面的觸發(fā)器節(jié)點(diǎn)。注意有些舊版本W(wǎng)orkbench的觸發(fā)器列表不顯示需要右鍵表選擇“Alter Table”在里面看Triggers選項卡。圖形客戶端的優(yōu)勢是直觀劣勢就是不夠批量。如果觸發(fā)器數(shù)量多或者需要過濾、統(tǒng)計還是推薦SQL方式。3. 實(shí)操在真實(shí)環(huán)境里把觸發(fā)器查清楚說再多理論不如實(shí)際跑一遍。我?guī)Т蠹易咭惶淄暾膶?shí)操流程大家可以直接對照著自己庫里試。3.1 造一張演示表和兩個觸發(fā)器先建一個簡單的訂單表再模擬兩個常見觸發(fā)器一個在插入訂單時自動寫一條操作日志一個在更新訂單金額時自動加一個校驗(yàn)或者同步動作。CREATE DATABASE IF NOT EXISTS demo_db DEFAULT CHARACTER SET utf8mb4; USE demo_db; CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL, amount DECIMAL(10,2) NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 0, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB; CREATE TABLE order_logs ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, action VARCHAR(64) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB; DELIMITER $$ CREATE TRIGGER trg_order_after_insert AFTER INSERT ON orders FOR EACH ROW BEGIN INSERT INTO order_logs(order_id, action) VALUES (NEW.id, INSERT); END$$ DELIMITER ; DELIMITER $$ CREATE TRIGGER trg_order_before_update BEFORE UPDATE ON orders FOR EACH ROW BEGIN IF NEW.amount OLD.amount THEN INSERT INTO order_logs(order_id, action) VALUES (NEW.id, CONCAT(AMOUNT_CHANGE_, OLD.amount, _TO_, NEW.amount)); END IF; END$$ DELIMITER ;注意一下我在觸發(fā)器里用了DELIMITER $$這是因?yàn)樵趍ysql客戶端里默認(rèn)分號就是語句結(jié)束符如果不臨時切換分隔符CREATE TRIGGER在第一條分號處就會提前結(jié)束導(dǎo)致語法錯誤。這個細(xì)節(jié)看起來基礎(chǔ)但真的是新手翻車重災(zāi)區(qū)。3.2 按表查、按庫查、按事件查現(xiàn)在我在demo_db庫里先用SHOW TRIGGERS看一眼全貌SHOW TRIGGERS FROM demo_db\G注意我用了\G在mysql命令行里這是把輸出結(jié)果轉(zhuǎn)成縱向顯示的關(guān)鍵觸發(fā)器語句長了以后橫向顯示會亂成一團(tuán)縱向輸出才是正經(jīng)姿勢。再試試按表定向查詢。我想知道orders表上都有哪些觸發(fā)器用SHOW TRIGGERS不好按表名過濾所以直接用information_schemaSELECT TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA demo_db AND EVENT_OBJECT_TABLE orders\G如果只看某個觸發(fā)器的完整定義SHOW CREATE TRIGGER demo_db.trg_order_after_insert\G你會發(fā)現(xiàn)輸出的SQL Original Statement中包含完整的CREATE DEFINER...TRIGGER ...語句這其實(shí)是做觸發(fā)器備份、遷移最靠譜的方式。我之前從5.7遷到8.0的時候就是用一條SQL查出所有觸發(fā)器的定義直接生成遷移腳本比在客戶端里一個個復(fù)制粘貼快得多。批量生成所有觸發(fā)器的重建腳本可以這樣寫SELECT CONCAT(SHOW CREATE TRIGGER , TRIGGER_SCHEMA, ., TRIGGER_NAME, ;) FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA demo_db;把結(jié)果逐條執(zhí)行再把每條結(jié)果里的SQL Original Statement收集起來就是一個完整的觸發(fā)器備份文件。3.3 把查看結(jié)果變成完整的排障報告光會執(zhí)行命令還不夠排障時要能把結(jié)果串起來。我通常的做法是先查全量確認(rèn)數(shù)量和總覽再按表篩選確認(rèn)范圍最后對重點(diǎn)觸發(fā)器看完整定義。順序不能反因?yàn)橄热吭倏磫螚l定位問題的路徑才是最優(yōu)的。舉個例子。有一次生產(chǎn)環(huán)境發(fā)現(xiàn)goods表的數(shù)據(jù)總是一致性異常我先執(zhí)行SELECT TRIGGER_NAME, EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA shop;很快就定位到有3個觸發(fā)器都掛在goods表上其中一個AFTER UPDATE觸發(fā)器嫌疑最大。接著查它的完整定義SHOW CREATE TRIGGER shop.trg_goods_update_sync\G結(jié)果看到里面有一句UPDATE other_table SET ...也就是每UPDATE一次商品就會同步更新另一張表的一大堆字段。但問題是該表數(shù)據(jù)量大觸發(fā)器執(zhí)行時間比主操作本身還長。最后和開發(fā)確認(rèn)這個觸發(fā)器已經(jīng)不需要了直接禁用掉異常就消失了。這就是觸發(fā)器查看的實(shí)際價值——不是“看一眼有沒有觸發(fā)器”這個動作本身而是通過查看把隱藏的副作用挖出來給后續(xù)決策提供依據(jù)。4. 踩坑記錄查看觸發(fā)器時最容易翻車的地方查觸發(fā)器看著簡單實(shí)際操作里各種坑我基本都踩過。下面這些是我覺得最有必要分享的基本都屬于“沒人告訴你等你碰到再查就要花半天時間”的類型。4.1 權(quán)限不夠命令白敲我最開始接觸MySQL的時候用的還是一個只讀賬號敲SHOW TRIGGERS直接報錯ERROR 1227 (42000): Access denied; you need (at least one of) the TRIGGER privilege(s) for this operation這里涉及MySQL權(quán)限體系查看觸發(fā)器至少需要TRIGGER權(quán)限。如果你用的是普通只讀賬號想要查詢information_schema.TRIGGERS可能也會被限制具體表現(xiàn)為連SELECT都報權(quán)限拒絕或者能查到一部分庫但查不到全部。解決方式有兩層讓DBA授權(quán)執(zhí)行GRANT TRIGGER ON demo_db.* TO userhost;。如果是只讀場景也可以嘗試SHOW TRIGGERS看能不能命中已開放的權(quán)限項但實(shí)測不通用。實(shí)際經(jīng)驗(yàn)是給開發(fā)環(huán)境賬號直接開TRIGGER權(quán)限問題不大生產(chǎn)環(huán)境堅持最小權(quán)限原則但要保證DBA自己隨時能查。如果你連TRIGGER權(quán)限都沒有又急需查看臨時讓DBA開個只讀會話也可以接受。4.2 8.0之后 mysql.proc 沒了以前在MySQL 5.7時代有些老DBA會通過直接查詢mysql.proc表來查看觸發(fā)器、存儲過程、函數(shù)之類的定義。很多遺留教程也是這么教的。但是MySQL 8.0把mysql.proc表徹底移除了。你再去查SELECT * FROM mysql.proc; -- 8.0直接報錯會得到很直接的ERROR 1109 (42S02): Unknown table proc in mysql。正確姿勢就是我用前面講的information_schema.TRIGGERS和SHOW CREATE TRIGGER這兩條路在8.0里都是官方支持的穩(wěn)定可靠。順帶提醒一句如果你從5.7升到8.0遷移工具可能也不會自動處理老觸發(fā)器務(wù)必用SHOW CREATE TRIGGER先備份再遷移否則你升完級會發(fā)現(xiàn)觸發(fā)器悄悄丟了。4.3 主從庫觸發(fā)器不一致問題最隱蔽觸發(fā)器在MySQL主從復(fù)制里有個大坑默認(rèn)情況下觸發(fā)器只在主庫執(zhí)行不會在從庫執(zhí)行。也就是說你在主庫建了觸發(fā)器從庫對應(yīng)表上的數(shù)據(jù)可能是對的因?yàn)閺膸旖邮盏氖侵鲙煲呀?jīng)做了觸發(fā)器處理的binlog但如果你在從庫單獨(dú)查觸發(fā)器會發(fā)現(xiàn)也許是空的。反過來如果你在主庫上用binlog_format STATEMENT且觸發(fā)器向其他表寫入數(shù)據(jù)主從復(fù)制可能遇到“從庫找不到觸發(fā)器定義”之類的異常。這些情況在金絲雀上線、臨時搭建只讀從庫時特別容易踩我之前就被人問過“為什么明明主庫有觸發(fā)器從庫數(shù)據(jù)還是會不一致”追到根因就是兩邊的觸發(fā)器集合沒有保持一致。所以查看觸發(fā)器時一定要主庫從庫分開查、定期對比不能默認(rèn)“主庫有從庫就有”。工具可以寫個定期巡檢腳本把主從的觸發(fā)器列表用information_schema.TRIGGERS拉出來做diff這不麻煩能防很多事故。4.4 字符集顯示亂碼還有一個容易忽略的點(diǎn)。觸發(fā)器新增數(shù)據(jù)時可能用到中文常量或者注釋如果你在客戶端查看客戶端連接字符集和觸發(fā)器創(chuàng)建時的字符集不一致會出現(xiàn)亂碼。經(jīng)典例子是SHOW TRIGGERS輸出看中文正常用腳本采集時卻發(fā)現(xiàn)亂碼或者SHOW CREATE TRRIGGER復(fù)制出來執(zhí)行后中文全變成問號。原因是character_set_client在觸發(fā)器創(chuàng)建會話里被固化成了當(dāng)時的連接字符集。查詢時如果當(dāng)前會話的字符集不同MySQL會做隱式轉(zhuǎn)換而轉(zhuǎn)換規(guī)則有時候并不如你所愿。處理原則是先統(tǒng)一字符集再查看。連接后立刻執(zhí)行SET NAMES utf8mb4;再去做查詢基本能避開大部分亂碼問題。如果還是亂碼檢查觸發(fā)器的character_set_client字段和當(dāng)前會話是否一致。4.5 觸發(fā)器語句太長默認(rèn)工具顯示不全這是最容易被誤解的一點(diǎn)。很多人用SHOW TRIGGERS看到Statement字段的最后是...以為是觸發(fā)器壞了。其實(shí)不是是顯示截斷。所以在查看較長觸發(fā)器時一定要用SHOW CREATE TRIGGER或者查information_schema.TRIGGERS.ACTION_STATEMENT字段。這兩個位置存儲的是完整語句不會被截斷。另外很多圖形客戶端的表格控件也會對超長文本做縮略顯示右鍵“復(fù)制單元格內(nèi)容”一般能看到全文。5. 面試番外知道怎么查還不夠觸發(fā)器這玩意兒面試也特別愛考。很多候選人說起觸發(fā)器張口就是“在表上放一段SQL自動執(zhí)行”但你說到具體怎么查、怎么排查、怎么備份他就卡殼了。只能說懂得不夠系統(tǒng)的還是多數(shù)。5.1 高頻三連問第一問MySQL有哪幾種觸發(fā)器事件答案BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE、BEFORE DELETE、AFTER DELETE為行級觸發(fā)器每張表同一事件可以存在多個觸發(fā)器按ACTION_ORDER順序執(zhí)行。第二問如何查看某張表上的觸發(fā)器標(biāo)準(zhǔn)回答是先SHOW TRIGGERS FROM 庫名快速看全量再用SELECT ... FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_TABLE表名做定向排查最后用SHOW CREATE TRIGGER查看完整定義。如果能順帶答出“SHOW TRIGGERS的Statement會被截斷、需要看ACTION_STATEMENT”這種細(xì)節(jié)面試印象會好很多。第三問觸發(fā)器對性能有什么影響這個更能考察理解的深度。答案要點(diǎn)觸發(fā)器在事務(wù)內(nèi)執(zhí)行執(zhí)行業(yè)務(wù)SQL和觸發(fā)器SQL的總時間會疊加如果觸發(fā)器里查了別的表行鎖會持有更久長觸發(fā)器還會增加死鎖概率。所以生產(chǎn)環(huán)境觸發(fā)器邏輯一定要短平快重邏輯應(yīng)該丟到應(yīng)用層異步處理。5.2 學(xué)習(xí)建議我個人建議觸發(fā)器能不用盡量別用尤其在大型分布式系統(tǒng)中會有維護(hù)成本。但如果你已經(jīng)接手了一套老系統(tǒng)觸發(fā)器滿天飛那想辦法先查清楚它們、做好備份和文檔化就已經(jīng)是很大的價值輸出。查是所有后續(xù)操作的前提一點(diǎn)虛的都不摻雜。6. 我的實(shí)操體會總結(jié)最后分享幾個“如果讓我重新查一遍我一定先做”的小建議。第一善用information_schema別死記硬背SHOW TRIGGERS的選項。我在實(shí)際工作中90%的觸發(fā)器查看都是用information_schema.TRIGGERS完成的因?yàn)樗С秩我庾侄芜^濾還方便用SQL拼接批量腳本這是SHOW命令不具備的能力。第二備份觸發(fā)器只用SHOW CREATE TRIGGER不要依賴圖形工具導(dǎo)出。我曾經(jīng)嘗試用Navicat的“轉(zhuǎn)儲SQL文件”導(dǎo)出觸發(fā)器結(jié)果發(fā)現(xiàn)它會帶上DELIMITER和一些版本相關(guān)的特殊字符換庫執(zhí)行時容易報錯。直接拿SHOW CREATE TRIGGER的輸出做成一份標(biāo)準(zhǔn)的DDL腳本反而干凈利落。第三查看觸發(fā)器之后順手檢查一下觸發(fā)器里引用的表、字段是否還存在。很多人建完觸發(fā)器后改表結(jié)構(gòu)直接把字段名改掉但觸發(fā)器還在引用舊字段。你平時不用它沒事一旦觸發(fā)條件滿足就是一連串報錯。查完觸發(fā)器確認(rèn)一下ACTION_STATEMENT里涉及的相關(guān)對象都健在能避免很多“莫名其妙”的錯誤。細(xì)算下來我從第一次被觸發(fā)器坑到如今把它玩得明明白白也就是靠多查、多踩、多想這六個字。這篇文章寫下來也算是我這些年查觸發(fā)器經(jīng)驗(yàn)的一個梳理。如果你對照著操作下來還有哪里跟你的環(huán)境不一致的多半要把目光放在版本差異和權(quán)限配置上這兩個變量是最大的“隱形差異項”。希望這篇對你有用祝大家查庫愉快少踩坑多省心。