mysql 中有這樣的一個默認行爲,若是一行數據中某些列被更新了,若是這一行中有timestamp類型的列,那麼麼這個timestamp列的數據mysql
也會被自動更新到 更新操做所發生的那個時間點;這個操做是由explicit_defaults_for_timestamp這個變動控制的sql
1、體驗一下mysql的默認更新行爲:session
mysql> create table t(x int ,y timestamp); -- 建立一個帶有timestamp列的表 Query OK, 0 rows affected (0.01 sec) mysql> insert into t(x) values(1); -- 只插x列 Query OK, 1 row affected (0.00 sec) mysql> select * from t; -- timestamp列會自動更新 +------+---------------------+ | x | y | +------+---------------------+ | 1 | 2017-06-07 13:48:56 | +------+---------------------+ 1 row in set (0.00 sec) mysql> update t set x=2 where x=1; -- update 時timestamp列仍是會自動更新 Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +------+---------------------+ | x | y | +------+---------------------+ | 2 | 2017-06-07 13:49:21 | +------+---------------------+ 1 row in set (0.00 sec)
2、如何關閉這一默認行爲:code
聰明的你一想到了,只要把explicit_defaults_for_timestamp這個變動設置爲on;對於timestamp列的值都要顯示指定,那麼這一默認行爲就ci
算是關閉了。來操做一把!it
mysql> set @@global.explicit_defaults_for_timestamp=on; -- 把全局的設置爲on 那麼新的鏈接就會被設置成on Query OK, 0 rows affected (0.00 sec) mysql> set @@session.explicit_defaults_for_timestamp=on; -- 把當前鏈接explicit_defaults_for_timestamp設置爲on Query OK, 0 rows affected (0.00 sec) mysql> update t set x=3 ; -- 第一次更新 結果是變了 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +------+---------------------+ | x | y | +------+---------------------+ | 3 | 2017-06-07 13:57:21 | +------+---------------------+ row in set (0.00 sec) mysql> update t set x=4 ; -- 第二次更新 結果仍是變了 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +------+---------------------+ | x | y | +------+---------------------+ | 4 | 2017-06-07 13:57:52 | +------+---------------------+ row in set (0.00 sec) mysql> show variables like 'explicit_defaults_for_timestamp'; -- 全局發動生效 +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | explicit_defaults_for_timestamp | ON | +---------------------------------+-------+ row in set (0.00 sec) mysql> show global variables like 'explicit_defaults_for_timestamp'; -- session 級別改動也升效了 +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | explicit_defaults_for_timestamp | ON | +---------------------------------+-------+ row in set (0.00 sec) -- 發現了吧、就算把explicit_defaults_for_timestamp 設置成了on 也不會有效的
3、找問題出在了哪裏:io
一、explicit_defaults_for_timestamp=off 時表結構table
CREATE TABLE `t` ( `x` int(11) DEFAULT NULL, `y` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- `y` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
二、explicit_defaults_for_timestamp=on 時表結構class
CREATE TABLE `t6` ( `x` int(11) DEFAULT NULL, `y` timestamp NULL DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- `y` timestamp NULL DEFAULT NULL
4、結論:變量
explicit_defaults_for_timestamp 變量會直接影響表結構,也就是說explicit_defaults_for_timestamp的做用時間
是在表定義的時候;你的update | insert 想經過它去改變行爲已經太晚了!
5、如何解決這失控的場面:
一、改表結構
mysql> alter table t modify column y timestamp null default null; -- 解決辦法改表結構 Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> update t set x=1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +------+---------------------+ | x | y | +------+---------------------+ | 1 | 2017-06-07 13:59:21 | +------+---------------------+ row in set (0.00 sec) mysql> update t set x=2; -- 再次對比,發現時間沒有變哦! Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +------+---------------------+ | x | y | +------+---------------------+ | 2 | 2017-06-07 13:59:21 | +------+---------------------+ row in set (0.00 sec)