三招教你解決零寬字符陷阱,讓你的數據庫不再”鬧鬼“。
作者:秦福朗,愛可生 DBA 團隊成員,負責項目日常問題處理及公司平臺問題排查。熱愛互聯網,會攝影、懂廚藝,不會廚藝的 DBA 不是好司機,didi~
愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
本文約 1000 字,預計閱讀需要 3 分鐘。
引言
在 MySQL 的使用過程中,有時候一個小小的字符也能帶來大麻煩,在未發現真相時,以爲這問題是見了鬼了,而發現真相時,卻沒想到是一個字符帶來的問題,零寬字符像個幽靈隱藏在 IT 行業的各個方面,今天分享一個關於 MySQL 中“消失的表”的復現案例。
問題描述
通過某種方式(如命令行或數據庫開發工具等)在數據庫 test
中創建了一個名爲 lang
的表。表結構如下:
CREATE TABLE `lang` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵自增',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
通過 SHOW TABLES;
命令,我們可以確認這個表的存在。
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| a1 |
| lang |
| t1 |
| z1 |
+----------------+
4 rows in set (0.00 sec)
但是,當你嘗試在 MySQL 客戶端執行 SELECT * FROM lang;
查詢或者業務程序去連接該表時,卻收到了錯誤信息:
mysql> select * from lang;
ERROR 1146 (42S02): Table 'test.lang' doesn't exist
表就這麼神奇的消失了。
原因分析
像見了鬼一樣,即使反覆多次手動輸入查詢語法,也無法查詢到這個表。我們將建表語句複製到 Sublime Text 文本工具中:
此時,我們發現了問題:表名後面跟了一個**“<0×200b>”**的字符。這就是零寬空格,是零寬字符的一種。
什麼是零寬字符?
零寬字符是一種特殊的 Unicode 字符,它不佔用任何可見空間,因此在大多數情況下是不可見的。然而,它們可以存在於文本中,並且可能對計算機程序產生影響,包括數據庫管理系統。在 Unicode 中,U+200B 代表零寬空格,常用於可能需要換行的地方。除此之外,還有其他零寬字符,這裏不再贅述。
那麼,這像幽靈一樣的字符爲何會存在? 所謂存在即合理,零寬字符常常被用於數據防爬、信息加密傳遞、防止敏感詞掃描等場景。但在數據庫系統裏使用,有時候就會出現讓人頭疼的現象,本文提到的就是其中之一。這些字符雖然不佔用任何空間,但可能會破壞 SQL 命令的正確結構,導致後續使用出錯。
如何解決?
- 在創建表之前,將建表語句複製到多個文本編輯工具,檢查是否有異常符號提示(一般文本工具可能無法顯示零寬字符)。經過嘗試 Sublime Text、Visual Studio Code 等工具或插件有提醒零寬字符的功能;還有一些在線網頁工具可以查看 Unicode 字符的功能。如果你知道其他能夠展示零寬字符的工具,歡迎在評論區留言分享。
- 在創建表之後,使用
SHOW CREATE TABLE;
命令查看錶結構,然後將輸出結果複製到上述文本編輯工具中,檢查是否有異常符號。 - 經過多次測試發現,在 MySQL 客戶端上執行了
SHOW TABLES;
命令時,含有零寬空格的表名後面的邊框線 “|” 與其他行是不對齊的。 這可以快速發現問題表,但並不顯示具體字符。當然這方式一般不適用於第三方開發工具、業務程序等。
總結
零寬字符是一個隱形的陷阱,可能在 MySQL 的使用過程中引發一些看似無解的問題。通過了解其本質,仔細檢查 SQL 命令,避免從不可靠的來源複製和粘貼,使用適當的工具,並遵循最佳實踐,我們可以確保我們的數據庫順利運行,不會出現類似問題。
更多技術文章,請訪問:https://opensource.actionsky.com/
關於 SQLE
SQLE 是一款全方位的 SQL 質量管理平臺,覆蓋開發至生產環境的 SQL 審覈和管理。支持主流的開源、商業、國產數據庫,爲開發和運維提供流程自動化能力,提升上線效率,提高數據質量。