-
Notifications
You must be signed in to change notification settings - Fork 441
the "SET NAMES" change in mysqlclient 1.4.4 seems to break a case on MySQL 8.0 #383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I suppose you are using old (< MySQL 8.0) client library to connect MySQL 8.0. MySQL CLI will produce a same error when CLI is 5.7 and Server is 8.0. For example, we use When user wants to specify collation per-column basis, the query is wrong. On the other hand, when user wants to use single collation in whole the application, |
I can confirm that building against MySQL 8.0 client library, the error does not occur. However, using pymysql, the error does occur. in all cases, SQLAlchemy's emitting of "SET NAMES" resolves the issue all around.
I am mostly concerned about the default case. For all the MySQLs until 8.0, no COLLATE is shown for any CREATE TABLE:
above is mariadb 10.3. Same behavior on MySQL 5.7, there's no COLLATION shown when I didn't specify one. For MySQL 8.0, there is:
the utf8mb4_0900_ai_ci collation looks to be all new in mysql 8.0. The older databases all seem to set collation_connection to "utf8_general_ci". MySQL 8, using the 8 client, sets it to "latin1_swedish_ci", which seems to have nothing to do with anything. Yet using the MySQL 8 client against server 8, the above "1271" error is not generated no matter what I do; the best I can do is specify collation in the SELECT and get "ERROR 1253 (42000): COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8mb4'". I don't know why I don't get that error if I don't specify the collation, since that's the default for collation_connection. Per MySQL 8 docs at https://dev.mysql.com/doc/refman/8.0/en/set-names.html, calling SET NAMES will set collation_connection to the default collation for that charset. As far as why one would not want to call "SET NAMES", and allow the case where these settings are not desirable as something that can be changed separately, it's not clear. It would appear that mysqlclient and its predecessor python-mysql have in fact been calling SET NAMES on every connection for 15 years, and this has not been a problem. Can you confirm this is the case ?
With all due respect, that SQL is ridiculous. The database should not need an obtuse COLLATE specification to match a NULL char column in a union. Also, this is not "the user", this is a SQL expression that's hardcoded in the SQLlchemy ORM and has to work across all databases, which it does. Databases like SQLite, Postgresql, SQL Server all have character collations as well as support for the "collate" keyword on a per-column basis yet none of them have such a requirement. MySQL's behavior is not reasonable, so as long as my call to "SET NAMES" is not going to cause any negative side effects and it resolves the need for this case, it will stay in. I would imagine that if the user is emitting CREATE TABLE with different kinds of collations, there might be issues, however IIUC, mysqlclient/python-mysql have emitted SET NAMES for years so we're still doing the best we can do here.
AFAICT this occurs implicitly:
I would only ask that the mysqlclient project appreciate that the removal of SET NAMES appears to be a major backwards incompatible change and this should have been called 1.5. |
Only when they want to use default collation. If they (including me) want to use other collation, they can not omit it.
I don't think this change is "major" and I don't want to call it 1.5 only for this change. |
that works for me as long as the vast majority of users who know nothing about this don't get weird collation errors all the sudden. mysql 8 has been causing a LOT of "suddenly dosen't work" types of situations, it has a lot of regressions like this and this
IMO if mysqlclient / python-mysql have been sending "SET NAMES " for about 10-15 years that would make this a major behavioral change. the state of the DB connection is now different when it first connects. |
It doesn't make sense unless this change affects MySQL server running from 10-15 years ago. The trouble is caused by not the change in this project. The trouble is caused by change in MySQL 8.0 and affects most mysql clients. |
OK just trying to get some truth on the best practice for this, it seems like calling SET NAMES has no real downside since it's what essentially happens when using a compatible client. at least that's what https://dev.mysql.com/doc/refman/8.0/en/charset-connection.html#charset-connection-client-configuration seems to say. |
Note that It is happens only when "charset" command is used. |
I just re-read this whole issue to re-familiarize, then i was like wow what did @yonran say to change your mind. I guess time has just passed. well in any case we're setting it also, not sure if that's wasteful. we could alternatetively just check it first but i doubt that really changes the net effect at all. |
Not only @yonran changed my mind. I reconsider this issue too. And I saw two Stackoverflow questions that @yonran mentioned in his issue. These questions may be caused by
Sending
I still don't like adding one round trip for every connection, because I don't like long living connections. |
thats right! sometimes it's worth it just to have people not asking you all the time. |
So it's not clear if this is actually a regression, because apparently PyMySQL has had this problem for awhile, but it just popped up on mysqlclient 1.4.4. Re-adding the "SET NAMES" mentioned in the changelog seems to fix it. I think MySQL 8.0 has a problem when SET NAMES is not called so if pymysql/mysqlclient won't add it back in I will likely have to add it to SQLAlchemy.
Test case:
this is using MySQL 8.0.16 running in Centos docker:
MySQLdb._exceptions.OperationalError: (1271, "Illegal mix of collations for operation 'UNION'")
It doesn't like the "CAST(NULL AS CHAR(50))" in the UNION. suddenly. adding back the SET NAMES makes it go away. only on MySQL 8, not on 5.7, 5.6, mariadb, etc.
Sorry this issue kind of sucks.
The text was updated successfully, but these errors were encountered: