整合階段 1 · 操作指南 · ← 寫入權矩陣 · 檢核清單 · 路線圖

拆掉 david:goalu 帳號要怎麼改

現在 16 個網站、一支 Windows 桌面程式、還有 68 個 stored procedure, 全都拿著同一把萬能鑰匙在寫資料庫——而那把鑰匙不只開得了 goalu, 它開得了這台機器上的每一個資料庫。 這頁講怎麼把它拆掉:先做哪一步、每站給什麼權限、怎麼驗、出事怎麼退。

權限清單不是人工寫的,是從寫入權矩陣直接算出來的; 矩陣重生,這頁的 SQL 就跟著變。

一、現在的問題長什麼樣

問題不是「有很多站連同一個資料庫」——那還算正常。問題是每一站都拿到了全部權限, 而且那個「全部」比想像中大得多。

連線端 ERP · salary · www forms · line · invoice report · sales · sony delivery · pbx ×2 inventory · story · kng.tw 16 個網站 Windows 桌面程式 8 台電腦 · 16 人 原盤點漏掉的第 17 個 david@% · tom@% ALL PRIVILEGES ON *.* 一把鑰匙,明碼寫在 5 個站的 PHP 裡 整台 MariaDB — 全部可寫 goalu(579 表) callhub ×5 muxue ×3 lk(學習王) shop rotary kn starmath · skilltree sin_shin · 以及未來新增的任何庫 任何一站被打穿 = 全機資料庫失守 連「刪掉整個 callhub 資料庫」都在權限內
圖 1現況。16 個網站與一支桌面程式共用 davidtom, 而這兩個帳號實測是 GRANT ALL PRIVILEGES ON *.*——不是「goalu 的全部權限」, 是這台機器上每一個資料庫的全部權限。 嘉南的官網若被打穿,攻擊者拿到的不只是客戶資料,還包括補習班系統、繪本站、學習王的資料庫。
這件事的嚴重性容易被低估

一般會想成「反正都是自己人的站,共用帳號沒差」。但共用帳號的代價不在信任,在事故半徑: 任何一站的 SQL injection、任何一個被猜到的密碼、任何一次手滑的 DELETE, 影響範圍都是全機而不是該站。而 david 的密碼明碼寫在 5 個站的 PHP 原始碼裡

二、為什麼「多個站在寫同一張表」特別麻煩

矩陣顯示 47 張表有兩個以上的寫入者,其中 hcust(客戶主檔)有 7 個。 但真正的問題不是「7 個地方會改客戶資料」,而是每一次改都會觸發一整串連鎖寫入—— 而那些連鎖是寫在資料庫裡的,改程式碼看不到。

7 個寫入者 ERP html/salary html/sales www forms delivery inventory 桌面 frmhcust hcust 客戶主檔 · 34.7 萬列 ↓ 一次 UPDATE 就自動觸發 6 個 AFTER UPDATE TRIGGER 寫在 DB 裡,改碼看不到 hcust_trd 業務異動核 · 468 萬列 call_data 電訪名單 · 64 萬列 帳務/配送/報表 下游全部受影響 另有 6 個 stored procedure 也在寫 hcust DEFINER 是 david@% —— 拆帳號時它們不受影響,但停用 david 時會全掛
圖 2連鎖寫入。hcust 上掛了 6 個 AFTER UPDATE trigger, 任何一站改客戶資料,都會自動再寫 hcust_trd(業務異動核)與 call_data(電訪名單)。 這些 trigger 寫在資料庫裡,看程式碼永遠看不到—— 也就是說「這支程式只改了客戶地址」在實際上等於「同時動了帳務與電訪」。

三、改完之後長什麼樣

每站一把自己的鑰匙 report line invoice ERP …其餘 12 站 report_app line_app invoice_app erp_app …各自帳號 goalu — 每站只看得到自己那幾張表 2 張寫入 + 42 張唯讀 11 張寫入 + 20 張唯讀 17 張寫入 + 28 張唯讀 63 張寫入(業務主力) 其餘 goalu 表 對該站完全不可見 連 SELECT 都會噴權限錯誤 ——這就是驗收的方法 SP/EVENT/TRIGGER 改用 goalu_scheduler,不再借用 david 的身分 callhub · muxue · lk · shop · rotary… 一律碰不到
圖 3目標。每站一個專屬帳號,只授權它實際用到的表—— 權限清單直接從矩陣算出來,不是憑感覺給的。 驗收方式很單純:在該站實測 SELECT 一張域外表,必須噴權限錯誤。 沒噴錯,就是還沒隔離成功。

四、五個步驟,順序不能換

這五步有明確的依賴關係:第 0 步隨時可做且立刻降風險, 中間三步可以慢慢推進,但最後一步(停用 david)有兩個前置門檻—— 桌面程式沒處理完、DEFINER 沒換完,就停 david 一定出事。

STEP 0 *.* → goalu.* 不改程式碼 今天就能做 STEP 1 逐站建專屬帳號 STEP 2 換 DEFINER STEP 3 桌面程式去留 這三項可以並行推進,各自有自己的節奏 STEP 1 不是硬門檻 但沒換完,停 david 就沒意義 門檻 這兩項沒做完 不准動 STEP 4 STEP 4 停用 david/tom 階段 1 出口條件 判定用 sys_log 與連線紀錄 連續 7 天歸零才算數
圖 4五步驟的依賴關係。 Step 0 是純收益:不改任何程式碼、不影響任何功能,就把事故半徑從「整台機器」縮到「一個資料庫」。 Step 1~3 可以並行,但 Step 4 必須等 Step 2 和 Step 3 都完成—— DEFINER 沒換就停 david,68 個 SP 和 20 個排程會全部失效; 桌面程式沒處理就停,會直接打斷 16 個人的日常作業。

五、每一步實際怎麼做

STEP 0 把權限範圍從全機收成單庫 不改程式碼 可立即執行

這一步不動任何程式碼、不改任何 .env、不需要停機, 卻立刻把事故半徑從「整台 MariaDB」縮到「goalu 一個庫」。應該最先做。

-- 先看清楚現在有什麼(一定要先看,下面有雷)
SHOW GRANTS FOR 'david'@'%';
SHOW GRANTS FOR 'david'@'localhost';
SHOW GRANTS FOR 'tom'@'%';

-- 收窄
REVOKE ALL PRIVILEGES, GRANT OPTION ON *.* FROM 'david'@'%';
GRANT ALL PRIVILEGES ON `goalu`.* TO 'david'@'%';

REVOKE ALL PRIVILEGES, GRANT OPTION ON *.* FROM 'tom'@'%';
GRANT ALL PRIVILEGES ON `goalu`.* TO 'tom'@'%';

FLUSH PRIVILEGES;
雷 · 收窄前一定要先確認單庫授權

david@localhost 另外還有 shopstarmathskilltree 的授權, tom 另有 invoicerotarykn。 這些是獨立的授權條目,收 *.* 不會動到它們—— 但如果某個站其實是靠 *.* 在存取那些庫(而不是靠單庫授權),收完就會斷。 所以SHOW GRANTS 對照,再動手

驗證 收窄後跑 SHOW GRANTS FOR 'david'@'%'; 應只剩 USAGE ON *.*ALL ON goalu.*; 然後開幾個站的主要頁面跑一輪(尤其 callhub、muxue、lk——它們用自己的帳號,本來就不該受影響)。

回退 GRANT ALL PRIVILEGES ON *.* TO 'david'@'%'; 一行還原,秒退。

STEP 1 逐站換成專屬最小權限帳號 一站一次 15 站

每站一個帳號、一次一站、一站一個 commit——這樣任何一站出事都能單獨回退, 不會變成「十五站一起壞、不知道是哪一站」。 建議從碰 goalu 最少的站開始,先把流程走順再處理大的。

順位站台新帳號寫入表唯讀表備註
1storystory_app 最好下手01幾乎不碰 goalu,用來把流程走順
2kng.twkngtw_app 留意12金流 callback 在這,切換後務必實測一筆
3pbxpbx_app 14兩套 pbx 並存,兩個都要換
4pbx-laravel12pbx12_app 14同上
5deliverydelivery_app 26
6html/reportreport_app 最好下手242讀 42 張表但只寫 2 張,典型的唯讀型站台
7html/sonysony_app 留意30明碼密碼寫在 admin/_inc/config.php,一併改 env
8html/salessales_app 留意611明碼密碼寫在 include/cndb.php,一併改 env
9formsforms_app 留意78對外收單入口,切換後實測一筆完整表單
10inventoryinventory_app 98目前用 tom 不是 david
11www.kngoatmilk.comwww_app 留意1117官網+對外 API,含金流 callback
12lineline_app 留意1120訊息量最大的站,切換挑離峰
13invoiceinvoice_app 留意1728發票開立,月結前後避開
14ERP(kngoatmilk)erp_app 最後做6329業務主力,應是多數表的唯一 writer。前面十四站的雷都踩完再動它
15html/salarysalary_legacy_app 最後做8745總務室本體。不一次拆,隨階段 5 逐模組搬遷

為什麼這個順序 寫入表越少,出錯面越小、驗證越快。 把最容易的放前面不是偷懶,是讓流程在低風險的站台上先跑通, 等到動 ERP(63 張)和 html/salary(87 張)時,該踩的雷已經踩完了。

單站的標準流程

① 建帳號 照矩陣 GRANT ② 先驗權限 域外表要噴錯 ③ 改 .env 切換 舊帳號還留著 ④ 觀察 ≥7 天 看 error log ⑤ 回收舊權限 這站才算完成 出事就把 .env 改回 david 舊權限還沒回收,所以隨時退得回去 ——這就是第 ⑤ 步要放最後的原因 密碼進 .env 不要寫死在 PHP
圖 5單站切換流程。關鍵是第 ⑤ 步(回收舊權限)必須放到最後—— 在那之前 david 的權限都還在,所以「把 .env 改回去」永遠是有效的回退手段。 觀察期沒過就急著回收,等於自斷退路。
STEP 2 把 SP/EVENT/TRIGGER 的 DEFINER 換掉 停用 david 的前置門檻

資料庫裡有 68 個有寫入的 stored procedure、20 個排程 EVENT(全部啟用中)、8 個 TRIGGER, 它們都以 DEFINER 的身分執行,而目前多數是 david@%。 這代表:就算 16 個站全都換好帳號,只要停用 david,這些東西會全部失效—— 包括每日估奶、電訪名單輪替、應收自動過帳、還有算薪。

-- 先盤點誰的 DEFINER 是 david
SELECT ROUTINE_TYPE, ROUTINE_NAME, DEFINER
  FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA='goalu' AND DEFINER LIKE 'david%';
SELECT EVENT_NAME, DEFINER, STATUS
  FROM information_schema.EVENTS   WHERE EVENT_SCHEMA='goalu';
SELECT TRIGGER_NAME, DEFINER
  FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA='goalu';

-- 建一個專門跑排程的身分
CREATE USER 'goalu_scheduler'@'localhost' IDENTIFIED BY '<PASSWORD>';
GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE ON `goalu`.* TO 'goalu_scheduler'@'localhost';
雷 · DEFINER 不能用 ALTER 直接改

MySQL/MariaDB 沒有「改 DEFINER」這種語法,必須用新身分重新 CREATE 一次DROPCREATE DEFINER=...)。所以動之前一定要先完整備份: mysqldump --routines --events --triggers --no-data goalu > goalu-routines-backup.sql

而且 EVENT 在 DROPCREATE 的空窗期如果剛好到執行時間,那一輪就跳過了。 挑離下次執行最遠的時段做,做完用 information_schema.EVENTS.LAST_EXECUTED 確認有跑。

驗證 換完等一個完整週期(多數是每日),比對 LAST_EXECUTED 有更新、 目標表的 UPDATE_TIME 有動、資料筆數符合預期。不要只看「沒報錯」—— 排程失效通常是安靜的。

STEP 3 決定那支 Windows 桌面程式怎麼辦 需要你的決定

這是整個階段 1 唯一技術上沒有標準答案、需要業務決策的一項。 sys_log 顯示它近 90 天有 214 筆操作、8 台電腦、16 個使用者,最近一次是 2026-08-17—— 使用量低,但確實還活著,而且碰的是客戶主檔與薪資。

表單對應業務筆數人數影響的表
frmhcust客戶維護17213hcust(+6 個 trigger 連鎖)
frmhum / frmhum_msar / frmhum_rpt*人資與薪資133humhum_msar
frmdept_work0 / frmdept_work部門工作102hum_*
frmhcust_ant_err / frmgcust_ant_edit應收帳款調整92hcust_antgcust_ant
frmsales_hcust_qty業務業績31sales_hcust_qty
frmhcust_mulist2 / frmhcust_mdqty / frmhcust_close_chk / frmvend名單/數量/結清/廠商7家戶相關

三個選項:

  1. 配專屬帳號 legacy_desktop(最省事)——照上表的表清單授權, 它就能繼續跑,同時 david 可以停用。缺點是這支程式繼續存在,帳號也得跟著留。
  2. 把功能搬到 web——frmhcust 一支就佔 172 筆/13 人, 搬完剩下的用量非常低。這條路最乾淨,但要花時間。
  3. 直接停用,看誰來喊——不建議:frmhum_msar 碰的是薪資, 而且 8 月才用過,停掉可能在月結時才爆。
順帶影響 · C2 薪資站驗收

frmhum_msar 會改 hum_msar, 表示新薪資站不是薪資資料的唯一入口。 9 月算薪驗收要把這件事算進去,否則會出現「新站顯示的跟實際不符,但查不出誰改的」。

怎麼判斷它退場了 查 sys_log,不要看 processlist—— 低頻使用的程式多數時間不在線上,看起來會像已經死了。

SELECT comp_name, prg_id, COUNT(*) n, MAX(mdate) last
  FROM goalu.sys_log
 WHERE mdate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
 GROUP BY 1,2 ORDER BY n DESC;
STEP 4 停用 david/tom 階段 1 出口條件

先確認兩個門檻都過了(Step 2 DEFINER 換完、Step 3 桌面程式處理完),然後:

  1. 先降權,不要直接刪帳號—— REVOKE ALL PRIVILEGES ON goalu.* FROM 'david'@'%';,帳號留著。 這樣出事的話一行 GRANT 就回來了。
  2. 觀察至少 7 天。期間看各站 error log、 information_schema.PROCESSLIST 有沒有 david 的連線、 以及 sys_log 有沒有新增(桌面程式)。
  3. 連續 7 天零異常,才 DROP USER
雷 · 別建同名的 localhost 影子帳號

MariaDB 的帳號比對是先精確後萬用:如果同時存在 david@%david@localhost, 從本機連線的會是後者。所以「我明明收了 david@% 的權限,怎麼還是寫得進去」 多半是因為 david@localhost 還在。兩個都要處理

六、每站的 GRANT 語句

下面每一段都是從寫入權矩陣直接算出來的, 不是人工整理的。點開即可複製。完整檔案: grants-draft.sql

用之前先讀這四條

① 密碼是 <PASSWORD> 佔位,執行時換掉,並寫進該站 .env 而不是 PHP 原始碼html/salaryreportsalessonykng.tw 五站目前是明碼寫死的)。
② 一站一次、一站一 commit。
③ 這是草稿不是定論:靜態掃描抓不到動態表名,切換後一定要跑該站的 smoke test。
④ 出現 DROP 權限的地方要特別看一眼——那是 TRUNCATE 需要的, 給了等於該站能砍表,確認真的在用再給。

story_appstory寫 0 · 讀 1 · 順位 1

繪本站 Laravel(目前用 tom,幾乎不碰 goalu)

-- story → story_app
-- 繪本站 Laravel(目前用 tom,幾乎不碰 goalu)
CREATE USER IF NOT EXISTS 'story_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 唯讀
GRANT SELECT ON `goalu`.`pbx_call_record` TO 'story_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'story_app'@'localhost';
kngtw_appkng.tw寫 1 · 讀 2 · 順位 2

集團入口與金流 callback(明碼密碼待改 env)

-- kng.tw → kngtw_app
-- 集團入口與金流 callback(明碼密碼待改 env)
CREATE USER IF NOT EXISTS 'kngtw_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, UPDATE ON `goalu`.`i_form` TO 'kngtw_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`hcust` TO 'kngtw_app'@'localhost';
GRANT SELECT ON `goalu`.`i_form_track` TO 'kngtw_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'kngtw_app'@'localhost';
pbx_apppbx寫 1 · 讀 4 · 順位 3

PBX 站 Laravel

-- pbx → pbx_app
-- PBX 站 Laravel
CREATE USER IF NOT EXISTS 'pbx_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`pbx_call_record` TO 'pbx_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`customers` TO 'pbx_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust` TO 'pbx_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_trd` TO 'pbx_app'@'localhost';
GRANT SELECT ON `goalu`.`pbx_token` TO 'pbx_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'pbx_app'@'localhost';
pbx12_apppbx-laravel12寫 1 · 讀 4 · 順位 4

PBX Laravel 12 版

-- pbx-laravel12 → pbx12_app
-- PBX Laravel 12 版
CREATE USER IF NOT EXISTS 'pbx12_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`pbx_call_record` TO 'pbx12_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`customers` TO 'pbx12_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust` TO 'pbx12_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_trd` TO 'pbx12_app'@'localhost';
GRANT SELECT ON `goalu`.`pbx_token` TO 'pbx12_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'pbx12_app'@'localhost';
delivery_appdelivery寫 2 · 讀 6 · 順位 5

配送站 Laravel

-- delivery → delivery_app
-- 配送站 Laravel
CREATE USER IF NOT EXISTS 'delivery_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`delivery_list` TO 'delivery_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust` TO 'delivery_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`address_book_indexes` TO 'delivery_app'@'localhost';
GRANT SELECT ON `goalu`.`customers` TO 'delivery_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_covers` TO 'delivery_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'delivery_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_sales` TO 'delivery_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'delivery_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'delivery_app'@'localhost';
report_apphtml/report寫 2 · 讀 42 · 順位 6

報表站(傳統 PHP,明碼密碼待改 env)

-- html/report → report_app
-- 報表站(傳統 PHP,明碼密碼待改 env)
CREATE USER IF NOT EXISTS 'report_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`ibadtrdcount` TO 'report_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`sys_sales` TO 'report_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`address_book_indexes` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`address_books` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`apart_comp` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`apart_sales` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`call_data` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`call_list` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`change_resources` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_gs` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`customers` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_dvs` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_sales` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_dv` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_ant` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dorder` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dorder_rt` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dv` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_token` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_trd` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`hum` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_day_qty` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_dv_record_copy3` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_visit_data` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`i_visit_group` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`iexpense` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`line_chat` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`order_records` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`pbx_call_record` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`pbx_call_transcript` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`rpt_delivery_achievement` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`rt10_list` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`sales_dvms` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`sales_report` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`trades` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`weekly_order_items` TO 'report_app'@'localhost';
GRANT SELECT ON `goalu`.`weekly_orders` TO 'report_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'report_app'@'localhost';
sony_apphtml/sony寫 3 · 讀 0 · 順位 7

皇銘 SONY 後台(明碼密碼待改 env)

-- html/sony → sony_app
-- 皇銘 SONY 後台(明碼密碼待改 env)
CREATE USER IF NOT EXISTS 'sony_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, UPDATE ON `goalu`.`sony_admin_user` TO 'sony_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sony_line_chat` TO 'sony_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sony_line_user` TO 'sony_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'sony_app'@'localhost';
sales_apphtml/sales寫 6 · 讀 11 · 順位 8

業務站(傳統 PHP,明碼密碼待改 env)

-- html/sales → sales_app
-- 業務站(傳統 PHP,明碼密碼待改 env)
CREATE USER IF NOT EXISTS 'sales_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust` TO 'sales_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_dorder` TO 'sales_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_trd` TO 'sales_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_visit_data` TO 'sales_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`i_visit_group` TO 'sales_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`payment` TO 'sales_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`apart_comp` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`apart_sales` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_ant` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dorder_rt` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dv` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_qtyf` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`sales_report` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_sales` TO 'sales_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'sales_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'sales_app'@'localhost';
forms_appforms寫 7 · 讀 8 · 順位 9

表單站 Laravel

-- forms → forms_app
-- 表單站 Laravel
CREATE USER IF NOT EXISTS 'forms_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT ON `goalu`.`SMS_log` TO 'forms_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust` TO 'forms_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_dorder` TO 'forms_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_trd` TO 'forms_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`i_form` TO 'forms_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`i_form_track` TO 'forms_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`rt10_list` TO 'forms_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`apart_comp` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`apart_sales` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`payment` TO 'forms_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_sales` TO 'forms_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'forms_app'@'localhost';
inventory_appinventory寫 9 · 讀 8 · 順位 10

庫存站 Laravel(目前用 tom)

-- inventory → inventory_app
-- 庫存站 Laravel(目前用 tom)
CREATE USER IF NOT EXISTS 'inventory_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, DELETE ON `goalu`.`date_tags` TO 'inventory_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`gcust_ml` TO 'inventory_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`hcust` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`hcust_trd` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`inventory_details` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`inventory_items` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`inventory_main` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`inventory_side_products` TO 'inventory_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`toy_stocks` TO 'inventory_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`daily_dvs` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_ml_items` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`hum` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`procedure_performance_logs` TO 'inventory_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'inventory_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'inventory_app'@'localhost';
www_appwww.kngoatmilk.com寫 11 · 讀 17 · 順位 11

官網與對外 API

-- www.kngoatmilk.com → www_app
-- 官網與對外 API
CREATE USER IF NOT EXISTS 'www_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`SMS_log` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_dorder` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_token` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_trd` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_form` TO 'www_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`i_form_track` TO 'www_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`line_chat` TO 'www_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`message_logs` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`payment` TO 'www_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`trades` TO 'www_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`address_book_indexes` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`address_books` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`cub_rcv` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`customers` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_cls` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_dorder` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_pre` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_ant` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dv` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_qtyf` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`i_rv_tp_area` TO 'www_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'www_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'www_app'@'localhost';
line_appline寫 11 · 讀 20 · 順位 12

LINE 站 Laravel

-- line → line_app
-- LINE 站 Laravel
CREATE USER IF NOT EXISTS 'line_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT ON `goalu`.`address_book_indexes` TO 'line_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`bug_reports` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`customers` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_token` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_form` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_chat` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_group_link` TO 'line_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`line_menu_clicks` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_unfollow` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`line_unlogin_assign` TO 'line_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`payment` TO 'line_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`address_books` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`cub_rcv` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_rcv` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_ant` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dv` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_qtyf` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`invoice_details` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`invoices` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`line_unlogin_list` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`posting_log` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`trades` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`weekly_order_items` TO 'line_app'@'localhost';
GRANT SELECT ON `goalu`.`weekly_orders` TO 'line_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'line_app'@'localhost';
invoice_appinvoice寫 17 · 讀 28 · 順位 13

發票站 Laravel

-- invoice → invoice_app
-- 發票站 Laravel
CREATE USER IF NOT EXISTS 'invoice_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT, UPDATE ON `goalu`.`SMS_log` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`apart_comp` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`apart_sales` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`call_empty` TO 'invoice_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`gcust_ant` TO 'invoice_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`hcust_ant` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_trd` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hum` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hum_con` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hum_nrdd` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hum_rel` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`i_deadline` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`iexpense` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`invoice_details` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`invoices` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sys_sales` TO 'invoice_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sys_uemp` TO 'invoice_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`address_book_indexes` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`call_data` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`call_list` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_gs` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_pms` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_price_details` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_prices` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`customers` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_orders` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_dv` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_price` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_pre` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_rcv` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dorder` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_qtyf` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hum_special_off` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`hum_wktime` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`i_sales_car` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`i_sales_daily` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`marea` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`pbx_call_record` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_pm` TO 'invoice_app'@'localhost';
GRANT SELECT ON `goalu`.`trades` TO 'invoice_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'invoice_app'@'localhost';
erp_appERP(kngoatmilk)寫 63 · 讀 29 · 順位 14

舊 ERP——應為多數業務表的唯一 writer,最後拆

-- ERP(kngoatmilk) → erp_app
-- 舊 ERP——應為多數業務表的唯一 writer,最後拆
CREATE USER IF NOT EXISTS 'erp_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, UPDATE, DELETE ON `goalu`.`address_book_indexes` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`address_books` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`change_resources` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`contacts` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`cron_alerts` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`cub_rcv` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`cub_record` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`customer_evens` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`customer_pms` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`customer_pre_jobs` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`customer_price_details` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`customer_price_templates` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`customer_prices` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`customers` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`daily_dvs` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`daily_gprod_jobs` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`daily_gprods` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`daily_orders` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`dv_covers` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`dv_dvms` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`dv_orders` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`element_events` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`estimate_runs` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`gcust_ant` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_cls` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_dorder` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`gcust_dv` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_even` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_ml` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_mu` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`gcust_narea_ant` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_price` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_price_classes` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_trd` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`gprod` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_amt_pre` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_amt_rcv` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_ant` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_ant_mk` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_dorder` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_dv` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_even` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_qtyf` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust_trd` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_trd_del` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_trd_rt` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`i_credit_qtyf` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_deadline` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_dvm_yn` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`i_prod_no_dvs` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`invoices` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`marea` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`marea_covers` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`order_records` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`price_templates` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sales_dept_performance_targets` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`sales_hcust_qty` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sys_pm` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`tasks` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`trades` TO 'erp_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`weekly_orders` TO 'erp_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`SMS_log` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`audits` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_gs` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_hs` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`daily_orders_shadow` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_orders_shadow` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_unit_price` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_close` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_ml_items` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_close` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_token` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`hum` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`i_day_qty` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`i_rv_tp_area` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`i_steambox_pos` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`invoice_details` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`jobs` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`line_chat` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`line_group_link` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`marea_cover_details` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`message_logs` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`posting_log` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`sales_dvm_products` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`sales_dvms` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_sales` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`task_results` TO 'erp_app'@'localhost';
GRANT SELECT ON `goalu`.`weekly_order_items` TO 'erp_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'erp_app'@'localhost';
salary_legacy_apphtml/salary寫 87 · 讀 45 · 順位 15

總務室本體,87 張表寫入。不一次拆,隨階段 5 逐模組搬

-- html/salary → salary_legacy_app
-- 總務室本體,87 張表寫入。不一次拆,隨階段 5 逐模組搬
CREATE USER IF NOT EXISTS 'salary_legacy_app'@'localhost' IDENTIFIED BY '<PASSWORD>';

-- 寫入
GRANT SELECT, INSERT ON `goalu`.`SMS_log` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE, DELETE ON `goalu`.`address_book_indexes` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE, DELETE ON `goalu`.`address_books` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`apart_sales` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`birthday_card_done` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`bug_reports` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`call_data` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`call_empty` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`call_empty_auto` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`change_resources` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`contacts` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`cron_alerts` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`cron_job_logs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`cron_jobs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`cron_permission_snapshots` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`cub_estimate` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`cub_rcv` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`cub_record` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`customer_evens` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE, DROP ON `goalu`.`customer_phone_index` TO 'salary_legacy_app'@'localhost';   -- ⚠️ DROP 是 TRUNCATE 需要的,確認真的在用
GRANT SELECT, INSERT ON `goalu`.`customer_price_details` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`customer_prices` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE, DELETE ON `goalu`.`customers` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`customers_gps` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`daily_orders` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`dv_orders` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`fax_print_log` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`fax_rotation` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`gcust` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`gcust_ant` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`gcust_ant_single` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`gcust_atm_posted` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`gcust_cls` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`gcust_narea_idno` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`hcust` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`hcust_token` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hcust_token_archive` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`hcust_trd` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`hum` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`hum_related_cust` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`hum_wktime` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_form` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`i_send_msg` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`i_steambox_pos` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`i_visit_data` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`i_visit_group` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`invoice_details` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`invoices` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_chat` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`line_chat_auto_reply_log` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_chat_summary` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`line_cs_quality_cases` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`line_cs_quality_jobs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`line_group_link` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`line_notice` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DROP ON `goalu`.`line_unlogin_list` TO 'salary_legacy_app'@'localhost';   -- ⚠️ DROP 是 TRUNCATE 需要的,確認真的在用
GRANT SELECT, UPDATE ON `goalu`.`marea` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`message_logs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`net_perf_ad_spend` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`net_perf_config` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`net_perf_settlement` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`notes` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`oldprice40_review_notes` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`order_records` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`orders_form_other` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`page_daily_access` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`page_info` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`payment` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`payment_attempts` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`payment_callback_failures` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`pbx_call_record` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`pbx_call_transcript` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`punch_hum_anyip` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`renewal_sms_log` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`rt10_list` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`salary2txt_log` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sony_line_chat` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE ON `goalu`.`sony_line_user` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT ON `goalu`.`sor_config` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`sor_extra` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, DELETE ON `goalu`.`sor_maintain_school` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE ON `goalu`.`sor_price` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE, DROP ON `goalu`.`sys_sidebar_menu` TO 'salary_legacy_app'@'localhost';   -- ⚠️ DROP 是 TRUNCATE 需要的,確認真的在用
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`trades` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, DELETE ON `goalu`.`weekly_order_items` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, UPDATE, DELETE ON `goalu`.`weekly_orders` TO 'salary_legacy_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `goalu`.`youtube_summaries` TO 'salary_legacy_app'@'localhost';

-- 唯讀
GRANT SELECT ON `goalu`.`ai_assets` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`ai_jobs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`apart_comp` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`call_list` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_gs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_hs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`customer_pms` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`delivery_list` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_covers` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_dvms` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`dv_unit_price` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_dorder` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_dv` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_ml` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_ml_items` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_mu` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gcust_trd` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gprod` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`gpu_jobs` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_pre` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_amt_rcv` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_ant` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dorder` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_dv` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hcust_qtyf` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hum_con` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hum_msar` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`hum_nrdd` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_deadline` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_dv_record_copy3` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_dvm_yn` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_form_track` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_prod` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`i_rv_tp_area` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`inventory_details` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`inventory_items` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`inventory_main` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`line_menu_clicks` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`line_unfollow` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`line_unlogin_assign` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`oldprice40_charged_cache` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`rpt_delivery_achievement` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_pm` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_sales` TO 'salary_legacy_app'@'localhost';
GRANT SELECT ON `goalu`.`sys_uemp` TO 'salary_legacy_app'@'localhost';

-- 驗證:新帳號連線後 SELECT 一張域外表,必須噴權限錯誤
-- SHOW GRANTS FOR 'salary_legacy_app'@'localhost';

七、怎麼確認真的改對了

每一步都有對應的驗證方式。共同原則是:不要只看「沒報錯」——權限問題經常是安靜地錯。

步驟驗證方式通過標準
STEP 0 SHOW GRANTS FOR 'david'@'%'; 只剩 USAGE ON *.*ALL ON goalu.*;callhub/muxue/lk 各站功能正常
STEP 1 用新帳號連線,SELECT 一張域外表 必須噴權限錯誤。查得到就是還沒隔離成功
STEP 1 該站 smoke test(登入+一個主功能的完整寫入流程) 功能正常,且 error log 無 SQLSTATE[42000]command denied
STEP 2 information_schema.EVENTS.LAST_EXECUTED 換 DEFINER 後一個週期內有更新,且目標表 UPDATE_TIME 有動
STEP 3 goalu.sys_log 近 30 天筆數 歸零(若選擇退場);或確認 legacy_desktop 帳號可正常運作
STEP 4 PROCESSLIST + 各站 error log + sys_log 連續 7 天零 david 連線、零異常

一段可以隨時跑的健檢

-- 還有誰在用 ALL ON *.*(應該逐漸歸零)
SELECT CONCAT(user,'@',host) AS account
  FROM mysql.global_priv
 WHERE JSON_VALUE(Priv,'$.access') > 0;

-- goalu 各帳號的授權範圍
SELECT GRANTEE, TABLE_SCHEMA, COUNT(*) AS n
  FROM information_schema.SCHEMA_PRIVILEGES GROUP BY 1,2;

-- 桌面程式還活著嗎
SELECT COUNT(*) AS ops_30d, COUNT(DISTINCT comp_name) AS pcs, MAX(mdate) AS last_seen
  FROM goalu.sys_log WHERE mdate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);

八、已知會踩的雷

症狀怎麼避
同名 @localhost 影子帳號 收了 david@% 的權限卻沒效果 MariaDB 先精確後萬用,@localhost 會勝出。兩個都要查、都要處理
DEFINER 沒換就停 david 排程與 trigger 安靜失效,通常月結才發現 STEP 2 是 STEP 4 的硬門檻,順序不可調
桌面程式沒盤點 停用 david 後 16 個人無法作業 sys_log 判活,不要用 processlist
TRUNCATE 需要 DROP 權限 為了一個清空動作,賦予了砍表的權限 先確認那個 TRUNCATE 真的還在用;能改成 DELETE 就改
REPLACE 需要 INSERTDELETE 只給 INSERT 會在執行期才失敗 草稿已自動處理,但手改時容易漏
靜態掃描漏動態表名 切換後某個少用功能突然權限不足 切換後保留 david 權限不回收,出事先改回 .env 再補授權
明碼密碼留在 PHP 換了帳號但密碼還是進了 git 五站(salary/report/sales/sony/kng.tw)要同步改讀 env

九、這頁刻意不處理的事