寫下這個(gè)標(biāo)題亦歉,我的內(nèi)心是復(fù)雜的恤浪。我們服務(wù)器的mysql接受了非法的enum值畅哑,但寫入時(shí)將值truncate掉了肴楷,也就是寫入了一個(gè)空的字符串,這個(gè)空的字符串會(huì)導(dǎo)致后續(xù)的代碼運(yùn)行異常荠呐,導(dǎo)致整個(gè)數(shù)據(jù)庫(kù)事務(wù)回滾赛蔫。數(shù)據(jù)庫(kù)里沒有任何記錄砂客,只能通過打更多l(xiāng)og一步一步地定位問題。最終定位出問題呵恢,已經(jīng)是N個(gè)小時(shí)后了鞠值。
為什么mysql接受了非法的enum值?在我們的固有印象中渗钉,mysql遇到非法的enum值應(yīng)該寫入失敗并報(bào)錯(cuò)彤恶。問題出在mysql的運(yùn)行參數(shù)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)
此時(shí)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報(bào)了一個(gè)warning且寫入的gender值是空的!瘫怜!
修改sql_mode值术徊,設(shè)置為嚴(yán)格模式
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
關(guān)于sql_mode可取的值以及不同值的含義赠涮,還請(qǐng)?jiān)儐杇oogle或官方文檔。