Skip to content
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

[5.6] Update MySqlConnector to be compatible to MySQL 8.0 #23948

Merged
merged 1 commit into from
Apr 25, 2018
Merged

[5.6] Update MySqlConnector to be compatible to MySQL 8.0 #23948

merged 1 commit into from
Apr 25, 2018

Conversation

rodrigopedra
Copy link
Contributor

With the release of MySQL 8.0.11 as GA (General Availability), the NO_AUTO_CREATE_USER sql_mode is invalid and the MySQL throws an error when trying to set it.

You can read more about removed features that should be noted before upgrading on:
https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html
(NO_AUTO_CREATE_USER related item is the first bullet in the Server Changes section)

https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals

For those who are migrating their MySQL servers to 8.0 and want a workaround, you can set the 'modes' array item in you database.php file:

// database.php

    'connections' => [

        'mysql' => [
            'driver'      => 'mysql',
            'host'        => env( 'DB_HOST', '127.0.0.1' ),
            'port'        => env( 'DB_PORT', '3306' ),
            'database'    => env( 'DB_DATABASE', 'forge' ),
            'username'    => env( 'DB_USERNAME', 'forge' ),
            'password'    => env( 'DB_PASSWORD', '' ),
            'unix_socket' => env( 'DB_SOCKET', '' ),
            'charset'     => 'utf8mb4',
            'collation'   => 'utf8mb4_unicode_ci',
            'prefix'      => '',
            'strict'      => true,
            'engine'      => null,
            'modes'       => [
                'ONLY_FULL_GROUP_BY',
                'STRICT_TRANS_TABLES',
                'NO_ZERO_IN_DATE',
                'NO_ZERO_DATE',
                'ERROR_FOR_DIVISION_BY_ZERO',
                'NO_ENGINE_SUBSTITUTION',
            ],
        ],
    ],

The modes listed above are the ones MySQL 8.0 uses as the default mode:
https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sql-mode-setting

@rodrigopedra rodrigopedra changed the title Update MySqlConnector to use MySQL 8.0 [5.6] Update MySqlConnector to be compatible to MySQL 8.0 Apr 20, 2018
@GrahamCampbell
Copy link
Member

This is a breaking change for mysql 7 users.

@rodrigopedra
Copy link
Contributor Author

Hi @GrahamCampbell thanks for your observation. what do you suggest instead?

Maybe create a different connector and have both mysql and mysql8 drivers?

@laurencei
Copy link
Contributor

laurencei commented Apr 20, 2018

For those who are migrating their MySQL servers to 8.0 and want a workaround...

So if there is already a workaround for mySQL v8 available now in Laravel 5.5/5.6 - then perhaps you could just put the mode change in Laravel 5.7 as a documented change, and mark that as having formal support for mySQL8?

Would seem to be less technical debt for Laravel to carry forward over the years, than trying to simulatenously support different versions (i.e. what your original PR was before the edit you just did)..

Just an idea... wait to see what Taylor says I guess.

@rodrigopedra
Copy link
Contributor Author

@GrahamCampbell , I thought about a solution and my suggestion is to add a 'version' option to the database configuration array.

If this PR gets accepted the configuration array in the database.php for a MySQL 8 connection can be written like this:

// database.php

    'connections' => [

        'mysql' => [
            'driver'      => 'mysql',
            'host'        => env( 'DB_HOST', '127.0.0.1' ),
            'port'        => env( 'DB_PORT', '3306' ),
            'database'    => env( 'DB_DATABASE', 'forge' ),
            'username'    => env( 'DB_USERNAME', 'forge' ),
            'password'    => env( 'DB_PASSWORD', '' ),
            'unix_socket' => env( 'DB_SOCKET', '' ),
            'charset'     => 'utf8mb4',
            'collation'   => 'utf8mb4_unicode_ci',
            'prefix'      => '',
            'strict'      => true,
            'engine'      => null,
            'version'     => 8,
        ],
    ],

I pushed a new commit to reflect this suggestion.

@rodrigopedra
Copy link
Contributor Author

@laurencei I agree with you when my first commit led to a breaking change. But if the amended version I see no reason to wait.

@rodrigopedra
Copy link
Contributor Author

@laurencei I saw your comment in the other related PR ( #23951 ) about carrying over the technical requirements for every new MySQL version.

I understand your argument, but I think that as MySQL has such wide adoption among web developers we should try to support all the versions that are currently supported by Oracle. Once Oracle drops support for an older version we could stop supporting it too.

@sisve
Copy link
Contributor

sisve commented Apr 20, 2018

You can read the mysql version from \DB::connection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION) and pick the proper sql modes from that, without having to let the user specify the version themselves.

@rodrigopedra
Copy link
Contributor Author

Thanks @sisve for the tip I am out of town for the weekend, when I am back later today I'll update the patch

{
if ($version === 8) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$version > 7 is probably safest, otherwise people are gonna get confused

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible they will put 7.4 8.0 or whatever into the config, and if we update to >, that'll still work. We could also take a string, and do a version_compare.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the commit to check against the PDO::ATTR_SERVER_VERSION attribute and the code now uses the > operator as you suggested.

@rodrigopedra
Copy link
Contributor Author

I edited from my iPad, so I couldn’t test against a runnin app. I compared to version 8.0.11 per release notes available at:

https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-server-changes

If someone can validate against a running mysql running at version 8.0.11 or up, I appreciate. Otherwise I'll validate when I’m back home later today.

{
if ($connection->getAttribute(PDO::ATTR_SERVER_VERSION) >= '8.0.11') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>= '8.0.11' doesn't do what you want. You need version_compare.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed a new commit using it. Thanks!

@rodrigopedra
Copy link
Contributor Author

rodrigopedra commented Apr 22, 2018

Can confirm it works. Tested with an app running Laravel 5.6.17 and MySQL 8.0.11.

In the last commit I changed the code to use the version_compare built-in php function as suggested by @GrahamCampbell

Already squashed the last 4 commits into one.

@ghost
Copy link

ghost commented May 15, 2018

excuse me I am using laravel 5.6.18 but i can't connect it to mysql 8.0.11 it says the following message

PDOException::(PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password])

it's posiible to fix it? or I need to wait

@rodrigopedra
Copy link
Contributor Author

rodrigopedra commented May 15, 2018

Hi @IngAlfredoPaz your case sounds like a MySQL installation error, not a Laravel issue, I found these links that may help:

If you migrated from a previous MySQL installation, there are two things to notice:

  1. During installation, the installer asks if you want to use the new password encryption for the DB users or to keep the old one for increased compatibility, in my installations I always choose to use the old one to avoid connection problems

  2. After upgrading from a current install you should run the mysql_upgrade utility to update the data structure used by MySQL.

One other thing you could try is to check if you are using the latest version from the php-mysql extension.

Sorry if you already tried all of these steps, but unfortunately I don't see how I could help further more as it doesn't seem to be a Laravel issue.

@ghost
Copy link

ghost commented May 15, 2018

@rodrigopedra you¿re so right, with the first step I did it thank you so much

@david-alan-oneill
Copy link

If your using windows and installed MySQL through the installer, relaunch the installer and you will see a reconfigure option beside the server. Click that and when you get back to the authentication part choose legacy. Relaunch cmd and migrate command will now work with no changes to database.php

@chilio
Copy link

chilio commented Jul 18, 2018

@rodrigopedra I am still stuck on this. I know how to reconfigure mysql server, etc
Unfortunately these solutions doesn't fit into this scenario....
I use mysql docker image for CI (Laravel Dusk) tests in gitlab, so there is no configuration (I don't want to bloat test spec, with additional commands). I am only specifying image name and version like service: mysql:5.7 or mysql:8.0. I could build another mysql image as a workaround, but sticking to the official ones seems much better.
So to summarize starting from mysql 8.0.4 I get The server requested authentication method unknown to the client error.
Do you have any suggestions for me?

@rodrigopedra
Copy link
Contributor Author

Hi @chilio , I don't have a clue of what can be happening. Googling for this error I found this issue in the laradock project:

laradock/laradock#1392 (comment)

The people over there seems to be having similar issues than you. Some says the solution I linked above works. Reading the thread I think that most people that suggests to delete the MySQL data folder doesnt know about running mysql_upggrade` after updating the version.

Take a look on what they suggest in that thread and if you succeed drop a line here.

Good luck.

@igoralves1
Copy link

It seems not to be an issue of Laravel. It seems to be an issue of php. PHP is not ready yet for this kind of encryption.

MySQL 8

When running a PHP version before 7.1.16, or PHP 7.2 before 7.2.4, set MySQL 8 Server's default password plugin to mysql_native_password or else you will see errors similar to The server requested authentication method unknown to the client [caching_sha2_password] even when caching_sha2_password is not used.

This is because MySQL 8 defaults to caching_sha2_password, a plugin that is not recognized by the older PHP (mysqlnd) releases. Instead, change it by setting default_authentication_plugin=mysql_native_password in my.cnf. The caching_sha2_password plugin will be supported in a future PHP release. In the meantime, the mysql_xdevapi extension does support it.

[http://php.net/manual/en/ref.pdo-mysql.php]

@fokosun
Copy link

fokosun commented Sep 6, 2019

'modes'       => [
                'ONLY_FULL_GROUP_BY',
                'STRICT_TRANS_TABLES',
                'NO_ZERO_IN_DATE',
                'NO_ZERO_DATE',
                'ERROR_FOR_DIVISION_BY_ZERO',
                'NO_ENGINE_SUBSTITUTION',
            ],

Didn't fix it for me

@99linesofcode
Copy link

Those issues are entirely unrelated to this PR. If you run into The server requested authentication method unknown to the client error, please refer to laradock/laradock#1392 (comment)

@pratikid
Copy link

pratikid commented Mar 3, 2020

Try installing php-mysqlnd and mysqli using yum or other package managers.

PHP Version: 7.4
MySQL Verison: 8.0.11

Ensure output of below command:

php -m | grep 'mysql'

Gives below output:

mysqli
mysqlnd

Works for me.

@SalasMerlitoJr
Copy link

C:\xampp\htdocs\Ecommerce>php artisan key:generate
Application key set successfully.

C:\xampp\htdocs\Ecommerce>php artisan migrate

Illuminate\Database\QueryException : SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES) (SQL: select * from information_schema.tables where table_schema = homestead and table_name = migrations)

at C:\xampp\htdocs\Ecommerce\vendor\laravel\framework\src\Illuminate\Database\Connection.php:664
660| // If an exception occurs when attempting to run a query, we'll format the error
661| // message to include the bindings with SQL, which will make this exception a
662| // lot more helpful to the developer instead of just the database's errors.
663| catch (Exception $e) {

664| throw new QueryException(
665| $query, $this->prepareBindings($bindings), $e
666| );
667| }
668|

Exception trace:

1 PDOException::("SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES)")
C:\xampp\htdocs\Ecommerce\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70

2 PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=homestead", "homestead", "secret", [])
C:\xampp\htdocs\Ecommerce\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70

please help me to fix it :(
Untitled

@rodrigopedra
Copy link
Contributor Author

Hey @SalasMerlitoJr ,

As you are using XAMPP and the database credentials are for the default ones for a Laravel Homestead installation, it seems your database credentials are not the same as your local MySQL installation.

Check your .env file if you have the same values for the DB_HOST, DB_DATABASE, DB_USERNAME, and DB_PASSWORD variables as your local MySQL instance requires.

Also, per contribution guidelines, this issue tracker is for reporting bugs with the framework itself. As your request seems more a support request, and not a bug report, please send further questions to the community support channels.

You can check the guidelines and the links to the community support channels at:

https://laravel.com/docs/8.x/contributions#support-questions

@SalasMerlitoJr
Copy link

@rodrigopedra noted sir .

@saidbakr
Copy link

With the release of MySQL 8.0.11 as GA (General Availability), the NO_AUTO_CREATE_USER sql_mode is invalid and the MySQL throws an error when trying to set it.

You can read more about removed features that should be noted before upgrading on: https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html (NO_AUTO_CREATE_USER related item is the first bullet in the Server Changes section)

https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals

For those who are migrating their MySQL servers to 8.0 and want a workaround, you can set the 'modes' array item in you database.php file:

// database.php

    'connections' => [

        'mysql' => [
            'driver'      => 'mysql',
            'host'        => env( 'DB_HOST', '127.0.0.1' ),
            'port'        => env( 'DB_PORT', '3306' ),
            'database'    => env( 'DB_DATABASE', 'forge' ),
            'username'    => env( 'DB_USERNAME', 'forge' ),
            'password'    => env( 'DB_PASSWORD', '' ),
            'unix_socket' => env( 'DB_SOCKET', '' ),
            'charset'     => 'utf8mb4',
            'collation'   => 'utf8mb4_unicode_ci',
            'prefix'      => '',
            'strict'      => true,
            'engine'      => null,
            'modes'       => [
                'ONLY_FULL_GROUP_BY',
                'STRICT_TRANS_TABLES',
                'NO_ZERO_IN_DATE',
                'NO_ZERO_DATE',
                'ERROR_FOR_DIVISION_BY_ZERO',
                'NO_ENGINE_SUBSTITUTION',
            ],
        ],
    ],

The modes listed above are the ones MySQL 8.0 uses as the default mode: https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sql-mode-setting

Indeed, it works, but for unknown reason, pluck() with keys & values pairs returns null values. More details in this Question

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet