mysql
mysql copied to clipboard
Set session timezone to UTC when loc is UTC and timezone undefined
Description
Accord to the proposal at #1114, implemented a change that will set the database session timezone to UTC when loc == nil
or loc
is UTC and the database time_zone
is not set.
Checklist
- [x] Code compiles correctly
- [x] Created tests which fail without the change (if possible)
- [x] All tests passing
- [x] Extended the README / documentation, if necessary
- [x] Added myself / the copyright holder to the AUTHORS file
In Mac tests are passing, but for Linux no. I'll boot my Linux PC later to try there and fix the problem
I think this is a breaking change, as MySQL uses the session time zone to parse the time string. Example:
package main
import (
"database/sql"
"fmt"
"time"
"github.com/go-sql-driver/mysql"
)
func main() {
dsn := mysql.NewConfig()
dsn.Params = map[string]string{"time_zone": "'+08:00'"}
dsn.ParseTime = true
dsn.Loc = time.UTC
dsn.User = "root"
dsn.DBName = "test"
db, err := sql.Open("mysql", dsn.FormatDSN())
if err != nil {
panic(err)
}
defer db.Close()
_, err = db.Exec("DROP TABLE IF EXISTS foo")
if err != nil {
panic(err)
}
_, err = db.Exec("CREATE TABLE foo (c TIMESTAMP(6))")
if err != nil {
panic(err)
}
_, err = db.Exec("INSERT INTO foo VALUES ('2020-10-01 05:12:34')")
if err != nil {
panic(err)
}
var r float64
err = db.QueryRow("SELECT UNIX_TIMESTAMP(c) FROM foo").Scan(&r)
if err != nil {
panic(err)
}
fmt.Println(int64(r))
}
If you change "time_zone": "'+08:00'"
to something else like "time_zone": "'+00:00'"
, the output varies.
Hi @breeswish, I will get back into this (sorry to have forgotten) but when the session timezone is set, there are no changes (shouldn't be)
The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]
The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]
What happen if the application is relying on the default timezone of MySQL?
The idea is to not be a breaking change since it will set the session time zone to the same as loc, only when loc is empty or UTC, but never overwrite user defined information [link here]
I have the same concern as @methane . Consider this scenario:
a. The default timezone of MySQL is a local time zone. Let's take local time zone is +08:00 as an example, the MySQL session default timezone is +08:00 now. b. The application uses go-mysql-driver contains the behavior: Insert a timestamp by using the human readable form: MySQL will parse this human readable form using the default time zone (+08:00) and store its UTC time value.
Note: the user does not explicitly specify a timezone using the driver, but is relying on the default time zone.
c. Now, if the driver starts to change the time zone by default, e.g. changing to UTC, the next stored time value will be broken. The broken time value can be easily found by selecting using UNIX_TIMESTAMP()
(which is not relying on the session time zone).
@methane @breeswish
This was what was happening with us, the database was -04:00 and we were not setting the session time zone, in database we had TIMESTAMP
fields, with an example of 2021-10-19T20:00:00-0400
, but when we get the date from the database, was loc
was nil
and assumed UTC
by default, we ended up with 2021-10-19T20:00:00Z
as the session timezone and loc
had different values [link to example]
The fact is that, if we had applications that doesn't set the session timezone and are treating data outside the driver, it can lead to a breaking change.
I think user should set time_zone
explicitly if it is needed.