From 7255306cc8c9aa9f0c76f8f3b70a288c0e68822f Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Mon, 12 Jun 2017 12:02:08 +0800 Subject: [PATCH] MDL-58729 database: Improve performance of CLI tool. Imporve the speed with which mysql_collation converts to a different collation. --- admin/cli/mysql_collation.php | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/admin/cli/mysql_collation.php b/admin/cli/mysql_collation.php index adaadbba6c7..ae3c709816b 100644 --- a/admin/cli/mysql_collation.php +++ b/admin/cli/mysql_collation.php @@ -53,7 +53,7 @@ Options: -h, --help Print out this help Example: -\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8_general_ci +\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8mb4_unicode_ci "; if (!empty($options['collation'])) { @@ -145,9 +145,22 @@ if (!empty($options['collation'])) { $skipped++; } else { - $DB->change_database_structure("ALTER TABLE $table->name DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation"); - echo "CONVERTED\n"; - $converted++; + try { + $DB->change_database_structure("ALTER TABLE $table->name CONVERT TO CHARACTER SET $charset COLLATE $collation"); + echo "CONVERTED\n"; + $converted++; + } catch (ddl_exception $e) { + $result = mysql_set_row_format($table->name, $charset, $collation, $engine); + if ($result) { + echo "CONVERTED\n"; + $converted++; + } else { + // We don't know what the problem is. Stop the conversion. + cli_error("Error: Tried to convert $table->name, but there was a problem. Please check the details of this + table and try again."); + die(); + } + } } $sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL"; @@ -290,3 +303,26 @@ function mysql_get_column_collations($tablename) { $rs->close(); return $collations; } + +function mysql_set_row_format($tablename, $charset, $collation, $engine) { + global $DB; + + $sql = "SELECT row_format + FROM INFORMATION_SCHEMA.TABLES + WHERE table_schema = DATABASE() AND table_name = ?"; + $rs = $DB->get_record_sql($sql, array($tablename)); + if ($rs) { + if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') { + $rowformat = $DB->get_row_format_sql($engine, $collation); + // Try to convert to compressed format and then try updating the collation again. + $DB->change_database_structure("ALTER TABLE $tablename $rowformat"); + $DB->change_database_structure("ALTER TABLE $tablename CONVERT TO CHARACTER SET $charset COLLATE $collation"); + } else { + // Row format may not be the problem. Can not diagnose problem. Send fail reply. + return false; + } + } else { + return false; + } + return true; +}