Found a strange inconsistency upon selecting rows from mysql 8.0.19 after some transaction on resultset (e.g. at mysqlworkbench by editing some rows).
(for reference this function: https://golang.org/pkg/database/sql/#DB.Query)
In others words db.Query(SQL)
returns the old state of my resultset (before editing and committing).
MYSQL rows before editing:
105 admin
106 user1
107 user2
109 user3
MYSQL rows after editing:
105 admin
106 user11
107 user22
109 user33
But Golang db.Query(SQL)
still continuously returns:
105 admin
106 user1
107 user2
109 user3
Does db.Query(SQL)
require being committed to maintain consistency with current database state? Because after I have added db.Begin()
and db.Commit()
it started to work consistently. Haven't tried other databases, doesn't look like a driver issue, or variable copy issue. It is bit odd coming from JDBC. Autocommit disabled.
The code:
func FindAll(d *sql.DB) ([]*usermodel.User, error) {
const SQL = `SELECT * FROM users t ORDER BY 1`
//tx, _ := d.Begin()
rows, err := d.Query(SQL)
if err != nil {
return nil, err
}
defer func() {
err := rows.Close()
if err != nil {
log.Fatalln(err)
}
}()
l := make([]*usermodel.User, 0)
for rows.Next() {
t := usermodel.NewUser()
if err = rows.Scan(&t.UserId, &t.Username, &t.FullName, &t.PasswordHash, &t.Email, &t.ExpireDate,
&t.LastAuthDate, &t.StateId, &t.CreatedAt, &t.UpdatedAt); err != nil {
return nil, err
}
l = append(l, t)
}
if err = rows.Err(); err != nil {
return nil, err
}
//_ = tx.Commit()
return l, nil
}
This is purely about MySQL MVCC (see https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html and https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html) and not Go/DB driver.
In short, if you start a transaction, read some data, then another transaction changes it and commits, you may or may not see the results, depending on the transaction isolation level set on the MySQL server.