When running this on one of my sites/servers, I get the following error:

Converting table: block
Converting table: block_role
Converting table: block_custom
Converting table: cache_block
Cannot modify header information - headers already sent by (output   [warning]
started at /usr/local/share/drush/includes/output.inc:38)
bootstrap.inc:1471
PDOException: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes: ALTER TABLE {cache_block} MODIFY cid varchar(255) CHARACTER SET :charset COLLATE :collation; Array
(
    [:charset] => utf8mb4
    [:collation] => utf8mb4_general_ci
)
 in DrupalCharsetConverter->convertTableFields() (line 174 of /home/geerlingguy/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc).
Drush command terminated abnormally due to an unrecoverable error.   [error]

Is there a way a check could be run to help the user figure out what the problem is / how to fix it? For most users, this is a bit cryptic.

See: http://stackoverflow.com/questions/1814532/1071-specified-key-was-too-lo...

CommentFileSizeAuthor
#19 capture- 22.jpg89.98 KBstephane bouillet

Comments

geerlingguy created an issue. See original summary.

geerlingguy’s picture

It looks like in my case, it was due to these two lines missing in the [mysqld] config inside my.cnf:

innodb_large_prefix = 1
innodb_file_format = barracuda

(As mentioned in the general Drupal.org documentation page: https://www.drupal.org/node/2754539).

I had to add those two lines and restart MySQL, then everything worked fine. We should maybe document this on the project page itself, in case people skim through the Drupal.org docs or don't see them at all, and only see this PDOException.

geerlingguy’s picture

Hmm... Note that on the same server, with a different database/site, I got a similar error, but for 1000 bytes, for the filter_format table:

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes: ALTER TABLE {filter_format} MODIFY format varchar(255) CHARACTER SET :charset COLLATE :collation; Array
(
    [:charset] => utf8mb4
    [:collation] => utf8mb4_general_ci
)
 in DrupalCharsetConverter->convertTableFields() (line 174 of /home/geerlingguy/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc).
geerlingguy’s picture

A quick fix (which isn't by any means recommended... but will help you get through the table conversions):

Manually change the VARCHAR column length in an affected table (with the 1000 byte limitation) to 250 instead of 255.

Apparently one of my databases was MyISAM—this was a really old database that started in Drupal 5, upgraded to 6, then 7, and was along the ride through many different servers/hosting companies! After I converted the tables from MyISAM to InnoDB, all was well in the world.

stefan.r’s picture

#2 is odd. Don't you get a The x:y MySQL database does not support UTF8MB4! Ensure that the conditions listed in settings.php related to innodb_large_prefix, the server version, and the MySQL driver version are met" warning when innodb_large_prefix is turned off?

It does a $connection->utf8mb4IsSupported() check, which should try to create a table with a large prefix, and show the warning. I wonder if you either missed the warning, or if this code is incorrect?



  public function utf8mb4IsSupported() {
    // Ensure that the MySQL driver supports utf8mb4 encoding.
    $version = $this->getAttribute(PDO::ATTR_CLIENT_VERSION);
    if (strpos($version, 'mysqlnd') !== FALSE) {
      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
      $version = preg_replace('/^\D([\d.]).*/', '$1', $version);
      if (version_compare($version, '5.0.9', '<')) { 
        return FALSE;    
      }         
    }           
    else {      
      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
      if (version_compare($version, '5.5.3', '<')) { 
        return FALSE;    
      }         
    }           
                
    // Ensure that the MySQL server supports large prefixes and utf8mb4.
    try {       
      $this->query("CREATE TABLE {drupal_utf8mb4_test} (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci ROW_FORMAT=DYNAMIC");
    }           
    catch (Exception $e) { 
      return FALSE;    
    }           
    $this->query("DROP TABLE {drupal_utf8mb4_test}");
    return TRUE;
  }

In any case, besides showing the warning, it should also *not try to convert* of course (it did previously), so committing a fix for that now.

  • stefan.r committed fd85569 on 7.x-1.x
    Issue #2762599: Skip utf8mb4 conversion when not supported
    
stefan.r’s picture

Just to add to this, we now convert all tables to InnoDB automatically.

geerlingguy’s picture

+1, thanks!

stefan.r’s picture

@geerlingguy just so I can evaluate whether to mark this as fixed, could you perhaps answer #6 by reverting to the old mysql settings/database and seeing if you can still reproduce the error in the OP in the latest version of the project? (Alpha4 I think)

geerlingguy’s picture

@stefan.r - sure thing! I'll test in a little bit and post the results here.

geerlingguy’s picture

Status: Active » Reviewed & tested by the community

@stefan.r - Everything works perfectly now; no errors whatsoever!

Also checked over your updates to the project page, and they're very helpful. I wrote up a quick blog post on it as well... hopefully it doesn't break drupal.org's Planet aggregator—is d.o upgraded to 7.50 yet?

stefan.r’s picture

Status: Reviewed & tested by the community » Needs review

@geerlingguy, that doesn't sound right :)

We *want* an error to appear when innodb_large_prefix is turned off. Is that what happens now?

Thanks a lot for the blog post!

geerlingguy’s picture

@stefan.r - Oops! Sorry about that, I had it turned on, was only testing the automatic InnoDB table conversion. I'll try to get the test setup again later.

ptmkenny’s picture

Version: 7.x-1.0-alpha2 » 7.x-1.0-alpha4

I'm getting a similar error on Pantheon:

17:bin pk$ terminus drush 'utf8mb4-convert-databases -y' --site=MYSITE --env=dev
[2016-07-12 03:47:19] [info] Running drush utf8mb4-convert-databases -y on MYSITE-dev
    cmd: 'utf8mb4-convert-databases -y'
    site: 'MYSITE'
    env: 'dev'
exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error     [error]
or access violation: 1071 Specified key was too long; max key length
is 767 bytes' in
/srv/bindings/d767913ee30941f3847c9361d2d787ba/code/includes/database/database.inc:2204
Stack trace:
#0
/srv/bindings/d767913ee30941f3847c9361d2d787ba/code/includes/database/database.inc(2204):
PDOStatement->execute(Array)
#1
/srv/bindings/d767913ee30941f3847c9361d2d787ba/code/includes/database/database.inc(683):
DatabaseStatementBase->execute(Array, Array)
#2
/srv/bindings/d767913ee30941f3847c9361d2d787ba/code/includes/database/database.inc(2383):
DatabaseConnection->query('ALTER TABLE {ca...', Array, Array)
#3
/srv/bindings/d767913ee30941f3847c9361d2d787ba/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc(175):
db_query('ALTER TABLE {ca...', Array)
#4
/srv/bindings/d767913ee30941f3847c9361d2d787ba/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc(143):
DrupalCharsetConverter->convertTableFields('cache_block', NULL, NULL)
#5
/srv/bindings/d767913ee30941f3847c9361d2d787ba/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc(116):
DrupalCharsetConverter->convertTable('cache_block', NULL, NULL)
#6
/srv/bindings/d767913ee30941f3847c9361d2d787ba/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc(64):
DrupalCharsetConverter->convertTables()
#7
/srv/bindings/d767913ee30941f3847c9361d2d787ba/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc(201):
DrupalCharsetConverter->convert(Array)
#8 [internal function]: drush_utf8mb4_convert_databases()
#9 /opt/pantheon/drush-8/includes/command.inc(366):
call_user_func_array('drush_utf8mb4_c...', Array)
#10 /opt/pantheon/drush-8/includes/command.inc(217):
_drush_invoke_hooks(Array, Array)
#11 [internal function]: drush_command()
#12 /opt/pantheon/drush-8/includes/command.inc(185):
call_user_func_array('drush_command', Array)
#13 /opt/pantheon/drush-8/lib/Drush/Boot/BaseBoot.php(67):
drush_dispatch(Array)
#14 /opt/pantheon/drush-8/includes/preflight.inc(66):
Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#15 /opt/pantheon/drush-8/drush.php(12): drush_main()
#16 {main}
This will convert all databases defined in settings.php to utf8mb4. Back up your databases before continuing! Continue? (y/n): y
Target MySQL database: default:default
Converting database: pantheon
Converting table: variable_store
Converting table: block
Converting table: block_role
Converting table: block_custom
Converting table: cache_block

A few notes:

  • Pantheon runs on nginx.
  • I am using 1.x-alpha4 version of this utility. I had to comment out the $connection->utf8mb4IsSupported() check because if I leave the check in I get this warning:

Target MySQL database: default:default
The default:default MySQL database does not support UTF8MB4! Ensure that the conditions listed in settings.php related to innodb_large_prefix, the server version, and the MySQL driver version are met. See https://www.drupal.org/node/2754539 for more information.

Despite this check, Pantheon's implementation of nginx does support utf8mb4. I know this because I previously used a different patch that ultimately was not committed to core to support emoji on my site. (Since upgrading to 7.50, I have undone this patch.)

Unfortunately although I use Drupal a lot my understanding of databases is limited so I'm not sure how to go about fixing this.

stefan.r’s picture

@geerlingguy any feedback on #13?

@ptmkenny, obviously you can't just comment out the support check -- if it fails, then yes, the conversion is going to fail :)

The warning is a bit unclear yes, it's not really true that "MySQL database does not support UTF8MB4"... just rather that your Pantheon etup doesn't seem to comply with some of the listed requirements in order to have UTF8MB4 support in Drupal core (which are stricter than the ones in earlier patches). So I'd check with them.

ptmkenny’s picture

@stefan.r Thanks for your input. I talked to Pantheon support, and they said that they do support uf8mb4. So I tried to dig into the matter deeper and this is what I found:

When it fails converting a table, the table that failed conversion will be the last one printed out, for example:

Converting table: cache_block

I can then look at that table and run a query on the first column like this:

ALTER TABLE cache_block CHANGE cid cid VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

Then I can re-run the command and a different table will fail. For example, commerce_order also failed. In the case of commerce_order, there are several columns:

order_number
type
mail
status
hostname

All of which are VARCHAR with an encoding/collation set, but I only needed to run the ALTER TABLE query manually for order_number, and then utf8mb4_convert was able to keep processing.

I'm not sure how to fix this but please let me know if this is helpful.

ptmkenny’s picture

Update: I heard back from Pantheon support again and actually at this time their database configuration does not meet all of the new 7.50 requirements.

stephane bouillet’s picture

StatusFileSize
new89.98 KB

Hi

as for me I had an old drupal install (4.7), evolved in drupal 7 now.
when doing the code
drush utf8mb4-convert-databases
it gives error:

Converting table: node_access
Cannot modify header information - headers already sent by (output started at /usr/share/php/drush/includes/output.inc:38)    [warning]
bootstrap.inc:1471
PDOException : SQLSTATE[HY000]: General error: 1214 The used table type doesn&#039;t support FULLTEXT indexes: ALTER TABLE {node_revision} ROW_FORMAT=DYNAMIC ENGINE=INNODB; Array
(
)
 dans DrupalCharsetConverter->convertTable() (ligne 134 dans /root/.drush/utf8mb4_convert/utf8mb4_convert.drush.inc).
Drush command terminated abnormally due to an unrecoverable error.   

After several try (nothing worked) to change the type of the table node_revision from MyINSAM to InnoDB, I finally compare the table node_revision with another site (younger) where the drush utf8mb4-convert-databases worked, and see the full text was in couple with the similar line.
So I deleted the line with "similar" in red, and make again the drush utf8mb4-convert-databases that finally worked.

Not sure that it is a good solution...?

thanks for advices