mysql Laravel SQLSTATE[22007]:无效的datetime格式:1292不正确的datetime值:'2019-03-10 02:00:39' for column 'updated_at'(daylight savings?)

0wi1tuuw  于 5个月前  发布在  Mysql
关注(0)|答案(2)|浏览(71)

我正在使用一个带有队列worker的Laravel应用程序,它刚刚开始失败并向日志中抛出一系列异常。下面是其中之一:

SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2019-03-10 02:00:39' for column 'updated_at' at row 1 (SQL: update `videos` set `updated_at` = 2019-03-10 02:00:39 where `id` = 30860)

字符串
需要注意的几点:

  • 时间戳 * 似乎 * 是正确的格式
  • 该列是MySQL TIMESTAMP类型(可空),使用InnoDB
  • updated_at字段由Laravel默认值管理,没有任何自定义日期格式
  • 我没有使用任何日期修改器,或者任何在保存之前会改变值的东西
  • 这段代码已经运行了几个星期没有任何问题
  • 最近没有更改代码
  • 我做了一个git checkout .composer install,以确保没有任何库文件被更改或损坏(没有更改)
    *错误首次出现在2019-03-10 02:00:39(UTC),即当地(中部)时间晚上8点

明尼苏达州2019年夏令时将于3月10日星期日凌晨2点开始
--谷歌
我在谷歌上能找到的所有东西都与某人使用了明显错误的时间格式有关,所以这并没有帮助我弄清楚。
我觉得从02:00 UTC 开始的错误与夏令时应该在02:00 US Central Time 开始开始的同一天之间有太多的巧合,但是我不知道为什么当时间戳由框架管理并在保存之前转换为UTC时会抛出这个错误(UTC不会为夏令时而改变)。
MySQL 5.5.45
Laravel 5.7.28
nesbot/carbon 1.36.2
简体中文
config/database.php:

'mysql' => [
    
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],


什么原因会导致日期值被识别为无效?

**Edit:**我已经确定这肯定是夏令时错误,因为时钟向前跳1小时,02:00和03:00之间的时间在美国中部时间是无效的。我不明白的是为什么应用程序上的TIMESTAMP字段设置为UTC会抛出错误?UTC如何受到夏令时的影响,当时间戳由框架(Laravel+Carbon)管理时,我可以做些什么来防止这种情况?

vsaztqbk

vsaztqbk1#

我发现这个问题是由于我的MySQL服务器的time_zone设置被设置为SYSTEM(我的系统是美国中央)。Laravel提供的时间戳已经转换为UTC,但由于time_zone设置,我的数据库将其解释为US Central。实际上,MySQL在内部 * 再次 * 将时间转换为“真实的”UTC unix时间戳表示(这将是不正确的,因为它的时区偏移),即使他们似乎是UTC已经在每一个查询,因为他们也得到转换回美国中部再次阅读(我知道的权利)。
因此,在20:00:39(8:00 PM)本地时间,我的Laravel UTC时间戳是02:00:39。MySQL将这些时间解释为美国中部时间,并且因为时间在02:00和03:00之间(这是美国中部的时钟向前跳的时间),所以时间无效。
Laravel应用程序的最佳解决方案是强制每个数据库连接使用+00:00时区(或您在config/app.php中设置为应用程序时区的任何时区),因此不会发生二次转换。这可以在config/database.php中完成:

'mysql' => [
    // ...

    'timezone'  => '+00:00'
],

字符串
这样,如果数据库服务器的时区配置与Laravel应用程序的时区不同,您就不会受到数据库服务器的支配。另一种选择是更改数据库的time_zone设置,但如果您更改主机或出于任何原因需要重建服务器(并且没有再次正确配置时区),或影响服务器上的其他数据库,则仍然存在bug复发的风险。
重要提示:由于所有以前的时间戳都被MySQL内部从配置的时区偏移到UTC unix时间戳(这又是错误的,因为记录已经是UTC),因此可能需要运行数据迁移来纠正旧的时间戳。我没有进一步调查,因为对于我的应用程序来说,旧的时间戳是否错误了几个小时并不重要。

i86rm4rw

i86rm4rw2#

这对我有帮助:config.datebase.mysql中的'strict' => false,

相关问题