I’m attempting to upgrade my Keycloak from 25.0.6 to 26.0.0. When starting the new version with the config file from the old version, it’s failing to update the MySQL database.
To do the update I stopped Keycloak, unzipped version 26.0.0, copied the keycloak.conf file to the new version, then ran kc.sh build --db=mysql --http-relative-path /auth which succeeds, followed by kc.sh start --optimized
Checking the log files I see this error line Oct 22 15:39:05 da-sso-02 kc.sh[1637838]: 2024-10-22 15:39:05,618 ERROR [liquibase.changelog.ChangeSet] (main) ChangeSet META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak encountered an exception.: liquibase.exception.DatabaseException: Duplicate column name 'TYPE' [Failed SQL: (1060) ALTER TABLE keycloak.KEYCLOAK_GROUP ADD TYPE INT DEFAULT 0 NULL]
I haven’t done any customization to the MySQL database. I just created the DB and gave Keycloak the credentials for it, letting Keycloak create/alter all its tables to get started.
Any idea what might be going wrong here and how to get it back on track?
The schema evolution is recorded in the table DATABASECHANGELOG
Try querying that table and see what’s in there;
SELECT * FROM DATABASECHANGELOG
ORDER BY DATEEXECUTED DESC
See what returns for this entry;
SELECT * FROM DATABASECHANGELOG
WHERE ID = '26.0.0-org-group'
I suspect that the schema evolution updated the KEYCLOAK_GROUP table but failed to write the update to the DATABASECHANGELOG table; and now you’re stuck because it thinks it needs to run it again but cannot. You may need to restore a backup of your database from prior to the update.
If this is a production instance, I’d advice against trying to bypass the tooling.
I decided to restore from a recent backup (before the attempt to update) and try again. It was possible that previous database was dirty from a different failed attempt to upgrade. This time it was on the server that had never had anything but the initial install and gradual upgrades with no issues.
Unfortunately it failed. But with a different message in the logs:
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,548 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to update database
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,548 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: liquibase.exception.LiquibaseException: liquibase.exception.MigrationFailedException: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: Reason: liquibase.exception.DatabaseException: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '=' [Failed SQL: (1267) UPDATE keycloak.KEYCLOAK_GROUP SET TYPE = 1 WHERE NAME IN (SELECT ID FROM keycloak.ORG)]
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,548 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: liquibase.exception.MigrationFailedException: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: Reason: liquibase.exception.DatabaseException: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '=' [Failed SQL: (1267) UPDATE keycloak.KEYCLOAK_GROUP SET TYPE = 1 WHERE NAME IN (SELECT ID FROM keycloak.ORG)]
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,550 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: Reason: liquibase.exception.DatabaseException: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '=' [Failed SQL: (1267) UPDATE keycloak.KEYCLOAK_GROUP SET TYPE = 1 WHERE NAME IN (SELECT ID FROM keycloak.ORG)]
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,551 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '=' [Failed SQL: (1267) UPDATE keycloak.KEYCLOAK_GROUP SET TYPE = 1 WHERE NAME IN (SELECT ID FROM keycloak.ORG)]
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,551 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '='
Oct 23 14:24:04 da-sso-02 kc.sh[7678]: 2024-10-23 14:24:04,551 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.
So referencing the same table but failing to update the column. Collations are getting a bit outside my understanding of MySQL. Hopefully that might be possible to fix? Any insight?
Sounds like there could be an encoding conflict with your database.
I found this in the Keycloak documentation;
=== Configuring Unicode support for a MySQL database
Unicode characters are supported in a MySQL database if the database was created with Unicode support in the VARCHAR and CHAR fields when using the CREATE DATABASE command.
Note that the utf8mb4 character set is not supported due to different storage requirements for the utf8 character set. See MySQL documentation for details. In that situation, the length restriction on non-special fields does not apply because columns are created to accommodate the number of characters, not bytes. If the database default character set does not allow Unicode storage, only the special fields allow storing Unicode values.
. Start MySQL Server.
. Under JDBC driver settings, locate the *JDBC connection settings*.
. Add this connection property: `characterEncoding=UTF-8`
Can you restore from backup again and try again with an updated connection string?
2024-10-28 14:53:39,159 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (production) mode
2024-10-28 14:53:39,159 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to update database
2024-10-28 14:53:39,160 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: liquibase.exception.LiquibaseException: liquibase.exception.MigrationFailedException: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Reason: liquibase.exception.DatabaseException: Duplicate column name ‘TYPE’ [Failed SQL: (1060) ALTER TABLE keycloak.KEYCLOAK_GROUP ADD TYPE INT DEFAULT 0 NULL]
2024-10-28 14:53:39,160 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: liquibase.exception.MigrationFailedException: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Reason: liquibase.exception.DatabaseException: Duplicate column name ‘TYPE’ [Failed SQL: (1060) ALTER TABLE keycloak.KEYCLOAK_GROUP ADD TYPE INT DEFAULT 0 NULL]
2024-10-28 14:53:39,161 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Reason: liquibase.exception.DatabaseException: Duplicate column name ‘TYPE’ [Failed SQL: (1060) ALTER TABLE keycloak.KEYCLOAK_GROUP ADD TYPE INT DEFAULT 0 NULL]
2024-10-28 14:53:39,161 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Duplicate column name ‘TYPE’ [Failed SQL: (1060) ALTER TABLE keycloak.KEYCLOAK_GROUP ADD TYPE INT DEFAULT 0 NULL]
2024-10-28 14:53:39,161 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Duplicate column name ‘TYPE’
2024-10-28 14:53:39,161 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the ‘–verbose’ option. Also you can use ‘–help’ to see the details about the usage of the particular command.
I tried options above and no success.
For test I create new DB and run start, it worked. But update from old fails. I’m using MySQL 8.0.32
I tried that. Restored from backup, everything’s ticking along happily under 25.0.6. Updated the db-url string in the .conf file - still works fine under 25.0.6. Updated to 26.0.0 and started it and got the same collation errors:
2024-10-29 15:08:38,386 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Migration failed for changeset META-INF/jpa-changelog-26.0.0.xml::26.0.0-org-group::keycloak:
Reason: liquibase.exception.DatabaseException: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb3_unicode_ci,IMPLICIT) for operation '=' [Failed SQL: (1267) UPDATE keycloak.KEYCLOAK_GROUP SET TYPE = 1 WHERE NAME IN (SELECT ID FROM keycloak.ORG)]
I poked back through my notes and found how I created the database in the first place:
CREATE DATABASE keycloakdb CHARACTER SET utf8 COLLATE utf8_unicode_ci;
If I recall, I was following some guides online, since I couldn’t fnd any official guidance from the Keycloak docs on creating the DB in MySQL. Perhaps I shouldn’t have had the COLLATE option on there? Do I need to change the COLLATE option on the DB, if that’s even possible?
By doing this you’re bypassing the schema update process which could have other unforeseen side-affects. If the database schema does not match what the Keycloak code expects you could get lots of bad errors. I’d advise against doing this in a production environment.
Well, it’s working now. Upgraded to 26.0.0 just now. Updating the thread in case anyone else has an issue like this.
I ended up updating the COLLATE setting for various columns in the database. Most columns had “utf8mb3_unicode_ci” as expected. About 20 or so were using the utf8_general_ci collation. I’m not sure why/how they got set that way as the DB was created with the utf8mb3_unicode_ci collation specified as default.
But after I updated the COLLATE setting for those columns, the upgrade went fine and everything is working well.
Updating the encoding types is definitely what I was would recommend. I’m not a DBA but for sure that seems like the underlying culprit here.
Dropping the column feels gross but, yeah, that’s probably what i’d have done too. After the upgrade is the column re-added correctly? As long as that’s the case I think it would be fine.
My other thought is that, since in your initial run the column was added but not rolled back either your driver or database aren’t configured to support transactions correctly – ideally if any part of the ChangeSet fails everything would be rolled back. Maybe look into using a XA driver? Just a thought to help prevent this from happening again in the future.
I am having the exact same issue. Did anyone filed a bug for this? Really strange. We have multiple (test) instances of KC an all of them are affected by this.
MySQL does not support transactional DDL - so no alter table … things can be rolled back. That is why this failure will always leave the DB in an inconsistent state regarding migrations.
I did not know that, thanks for the insight! I almost always go with postgres so I’m really unfamiliar with mysql configurations.
From what I’ve gathered, the root cause is that the database was created with the wrong default encoding; if you add characterEncoding=UTF-8 to your connection string and also update existing tables to use utf8mb3_unicode_ci that’s solved the issue for others.
You’d also need to drop / unalter any columns that are in that halfway state to deal with the non-transactional update…