為什麼mysql接受瞭非法的enum值,而不是寫入失敗並報錯?

寫下這個標題,我的內心是復雜的。我們伺服器的mysql接受瞭非法的enum值,但寫入時將值truncate掉瞭,也就是寫入瞭一個空的字符串,這個空的字符串會導致後續的代碼運行異常,導致整個資料庫事務回滾。資料庫裡沒有任何記錄,隻能通過打更多log一步一步地定位問題。最終定位出問題,已經是N個小時後瞭。

為什麼mysql接受瞭非法的enum值?在我們的固有印象中,mysql遇到非法的enum值應該寫入失敗並報錯。問題出在mysql的運行參數sql_mode。

mysql> show create table customer\G
*************************** 1. row ***************************
       Table: customer
Create Table: CREATE TABLE `customer` (
  `id` int(11) NOT NULL DEFAULT '0',
  `gender` enum('m','f') DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

mysql> select @@session.sql_mode;
+------------------------+
| @@session.sql_mode     |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)

此時sql_mode=NO_ENGINE_SUBSTITUTION ,嘗試寫入非法的enum值

mysql> insert into customer values (2,'x');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from customer where id=2\G
*************************** 1. row ***************************
    id: 2
gender: 
1 row in set (0.00 sec)

可以看到寫入成功瞭,但mysql報瞭一個warning且寫入的gender值是空的!!

修改sql_mode值,設置為嚴格模式

mysql> set sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)
mysql> 
mysql> select @@session.sql_mode;
+--------------------------------------------+
| @@session.sql_mode                         |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)

再次嘗試寫入,可以看出寫入失敗瞭。

mysql> insert into customer values (4,'x');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1

關於sql_mode可取的值以及不同值的含義,還請詢問google或官方文檔。

發佈留言