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

MySQL server gone away after drush php #1747

Closed
ameenross opened this issue Nov 5, 2015 · 8 comments
Closed

MySQL server gone away after drush php #1747

ameenross opened this issue Nov 5, 2015 · 8 comments

Comments

@ameenross
Copy link

This is with Drush and Drupal both at version 8.0.0-rc3.

It looks like for some reason it's trying to create the cache_config table, even though it exists. Apparently this happens after closing the connection to the database. Perhaps Drupal thinks the table is missing and tries to repair it?

$ ~/drush php
Psy Shell v0.5.2 (PHP 5.6.14 — cli) by Justin Hileman
>>> exit;
Error while sending QUERY packet. PID=7141 Statement.php:64                                                                                                                   [warning]
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away: CREATE TABLE {cache_config} (                                 [error]
`cid` VARCHAR(255) BINARY CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT 'Primary Key: Unique cache ID.', 
`data` LONGBLOB NULL DEFAULT NULL COMMENT 'A collection of data to cache.', 
`expire` INT NOT NULL DEFAULT 0 COMMENT 'A Unix timestamp indicating when the cache entry should expire, or -1 for never.', 
`created` DECIMAL(14, 3) NOT NULL DEFAULT 0 COMMENT 'A timestamp with millisecond precision indicating when the cache entry was created.', 
`serialized` SMALLINT NOT NULL DEFAULT 0 COMMENT 'A flag to indicate whether content is serialized (1) or not (0).', 
`tags` LONGTEXT NULL DEFAULT NULL COMMENT 'Space-separated list of cache tags for this entry.', 
`checksum` VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL COMMENT 'The tag invalidation checksum when this entry was saved.', 
PRIMARY KEY (`cid`), 
INDEX `expire` (`expire`)
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT 'Storage for the cache API.'; Array
(
)
 in Drupal\Core\Config\CachedStorage->readMultiple() (line 110 of /var/www/html/d8/core/lib/Drupal/Core/Config/CachedStorage.php).
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away: CREATE TABLE {cache_config} (
`cid` VARCHAR(255) BINARY CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT 'Primary Key: Unique cache ID.', 
`data` LONGBLOB NULL DEFAULT NULL COMMENT 'A collection of data to cache.', 
`expire` INT NOT NULL DEFAULT 0 COMMENT 'A Unix timestamp indicating when the cache entry should expire, or -1 for never.', 
`created` DECIMAL(14, 3) NOT NULL DEFAULT 0 COMMENT 'A timestamp with millisecond precision indicating when the cache entry was created.', 
`serialized` SMALLINT NOT NULL DEFAULT 0 COMMENT 'A flag to indicate whether content is serialized (1) or not (0).', 
`tags` LONGTEXT NULL DEFAULT NULL COMMENT 'Space-separated list of cache tags for this entry.', 
`checksum` VARCHAR(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL COMMENT 'The tag invalidation checksum when this entry was saved.', 
PRIMARY KEY (`cid`), 
INDEX `expire` (`expire`)
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT 'Storage for the cache API.'; Array
(
)
 in Drupal\Core\Config\CachedStorage->readMultiple() (line 110 of /var/www/html/d8/core/lib/Drupal/Core/Config/CachedStorage.php).
@ameenross
Copy link
Author

Looks like I was on the right track. Cache bins are (re)created when they're missing: https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Cache!DatabaseBackend.php/function/DatabaseBackend%3A%3AensureBinExists/8

That code calls \Drupal\Core\Database\Schema::tableExists, and here's the mysql implementation of it: https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Database!Driver!mysql!Schema.php/function/Schema%3A%3AtableExists/8

Apparently that contains a workaround for a MySQL bug (doesn't seem to be present in MariaDB). A "server went away" exception (or anything else) is therefore interpreted as "this table doesn't exist". That triggers \Drupal\Core\Cache\DatabaseBackend::ensureBinExists to try to create the table.

@damiankloip
Copy link
Contributor

ping @weitzman , this is the same problem you pinged me about yesterday.

I think the problem is because we are telling drush we are done early, stuff (not sure what yet) is happening in the Bootstrap 8 process, possible with the drush shutdown function. Then terminate is still called when the shell exits.

@dawehner
Copy link
Contributor

so yeah the problem is the following.
it you type in exit; this gets translated to 'return die;' in psych.
this die triggers all the destructors.
so the forked process id dead, which is kinda fine.
now we are back to the main process and run the terminate code, but too bad, we closed all the DB connections already.

@damiankloip
Copy link
Contributor

Yeah, so the main issue we have here is that PsySH uses a ForkingLoop, using pcntl. When the child process is killed, the database connection is also closed. Then when we return back to the parent (drush command), the command finishes, and terminate() stuff runs, which needs the database, which has now been closed.

So I guess we could try:

  1. Opening the connection again just after the shell has returned?
  2. Work out how to open the DB connection for each child process instead (not sure if that is possible for Drupal or not).
  3. Don't use the ForkingLoop, use the regular loop. This would fix the problem straight away. However, it isn't ideal as then the shell can just exist with fatal user input etc.. (So that would be the trade off I guess).

@dawehner
Copy link
Contributor

  1. Work out how to open the DB connection for each child process instead (not sure if that is possible for Drupal or not)

Well that just feels like a workflow for one special usecase to be honets

On Mon, Nov 16, 2015 at 2:28 PM, Damian Lee notifications@github.com
wrote:

Yeah, so the main issue we have here is that PsySH uses a ForkingLoop,
using pcntl. When the child process is killed, the database connection is
also closed. Then when we return back to the parent (drush command), the
command finishes, and terminate() stuff runs, which needs the database,
which has now been closed.

So I guess we could try:

  1. Opening the connection again just after the shell has returned?
  2. Work out how to open the DB connection for each child process
    instead (not sure if that is possible for Drupal or not).
  3. Don't use the ForkingLoop, use the regular loop. This would fix the
    problem straight away. However, it isn't ideal as then the shell can just
    exist with fatal user input etc.. (So that would be the trade off I guess).


Reply to this email directly or view it on GitHub
#1747 (comment).

@damiankloip
Copy link
Contributor

Potential fix : #1785

@damiankloip
Copy link
Contributor

@ameenross I just merged the fix for this problem, it should solve the issue for both D7 and D8 sites. Please give it a go! #1785

@ameenross
Copy link
Author

Cool, that solved the problem. Thx

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

No branches or pull requests

4 participants