Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * MySQL table row compression tool tool.
19
 *
20
 * @package   core
21
 * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 * @author    Petr Skoda <petr.skoda@totaralms.com>
24
 */
25
 
26
define('CLI_SCRIPT', true);
27
 
28
require(__DIR__.'/../../config.php');
29
require_once($CFG->libdir . '/clilib.php');
30
 
31
if ($DB->get_dbfamily() !== 'mysql') {
32
    cli_error('This script is used for MySQL databases only.');
33
}
34
 
35
$engine = strtolower($DB->get_dbengine());
36
if ($engine !== 'innodb' and $engine !== 'xtradb') {
37
    cli_error('This script is for MySQL servers using InnoDB or XtraDB engines only.');
38
}
39
 
40
list($options, $unrecognized) = cli_get_params(
41
    array('help' => false, 'info' => false, 'list' => false, 'fix' => false, 'showsql' => false),
42
    array('h' => 'help', 'i' => 'info', 'l' => 'list', 'f' => 'fix', 's' => 'showsql')
43
);
44
 
45
if ($unrecognized) {
46
    $unrecognized = implode("\n  ", $unrecognized);
47
    cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
48
}
49
 
50
$help =
51
    "Script for detection of row size problems in MySQL InnoDB tables.
52
 
53
By default InnoDB storage table is using legacy Antelope file format
54
which has major restriction on database row size.
55
Use this script to detect and fix database tables with potential data
56
overflow problems.
57
 
58
Options:
59
-i, --info            Show database information
60
-l, --list            List problematic tables
61
-f, --fix             Attempt to fix all tables (requires SUPER privilege)
62
-s, --showsql         Print SQL statements for fixing of tables
63
-h, --help            Print out this help
64
 
65
Example:
66
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_compressed_rows.php -l
67
";
68
 
69
/** @var mysql_sql_generator $generator */
70
$generator = $DB->get_manager()->generator;
71
 
72
$info = $DB->get_server_info();
73
$filepertable = $DB->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_per_table'");
74
$filepertable = $filepertable ? $filepertable->value : '';
75
$fileformat = $DB->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_format'");
76
$fileformat = $fileformat ? $fileformat->value : '';
77
$prefix = $DB->get_prefix();
78
$database = $CFG->dbname;
79
 
80
if (!empty($options['info'])) {
81
    echo "Database version:      " . $info['description'] . "\n";
82
    echo "Database name:         $database\n";
83
    echo "Database engine:       " . $DB->get_dbengine() . "\n";
84
    echo "innodb_file_per_table: $filepertable\n";
85
    echo "innodb_file_format:    $fileformat\n";
86
 
87
    exit(0);
88
 
89
} else if (!empty($options['list'])) {
90
    $problem = false;
91
    foreach ($DB->get_tables(false) as $table) {
92
        $columns = $DB->get_columns($table, false);
93
        $size = $generator->guess_antelope_row_size($columns);
94
        $format = $DB->get_row_format($table);
95
        if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
96
            continue;
97
        }
98
 
99
        echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT);
100
        echo str_pad($format, 11, ' ', STR_PAD_RIGHT);
101
 
102
        if ($format === 'Compact' or $format === 'Redundant') {
103
            $problem = true;
104
            echo " (needs fixing)\n";
105
 
106
        } else if ($format !== 'Compressed' and $format !== 'Dynamic') {
107
            echo " (unknown)\n";
108
 
109
        } else {
110
            echo "\n";
111
        }
112
    }
113
 
114
    if ($problem) {
115
        exit(1);
116
    }
117
    exit(0);
118
 
119
} else if (!empty($options['fix'])) {
120
    $fixtables = array();
121
    foreach ($DB->get_tables(false) as $table) {
122
        $columns = $DB->get_columns($table, false);
123
        $size = $generator->guess_antelope_row_size($columns);
124
        $format = $DB->get_row_format($table);
125
        if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
126
            continue;
127
        }
128
        if ($format === 'Compact' or $format === 'Redundant') {
129
            $fixtables[$table] = $table;
130
        }
131
    }
132
 
133
    if (!$fixtables) {
134
        echo "No changes necessary\n";
135
        exit(0);
136
    }
137
 
138
    if ($filepertable !== 'ON') {
139
        try {
140
            $DB->execute("SET GLOBAL innodb_file_per_table=1");
141
        } catch (dml_exception $e) {
142
            echo "Cannot enable GLOBAL innodb_file_per_table setting, use --showsql option and execute the statements manually.";
143
            throw $e;
144
        }
145
    }
146
    if ($fileformat !== 'Barracuda') {
147
        try {
148
            $DB->execute("SET GLOBAL innodb_file_format=Barracuda");
149
        } catch (dml_exception $e) {
150
            echo "Cannot change GLOBAL innodb_file_format setting, use --showsql option and execute the statements manually.";
151
            throw $e;
152
        }
153
    }
154
 
155
    if (!$DB->is_compressed_row_format_supported(false)) {
156
        echo "MySQL server is not compatible with compressed row format.";
157
        exit(1);
158
    }
159
 
160
    foreach ($fixtables as $table) {
161
        $DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
162
        echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
163
    }
164
 
165
    exit(0);
166
 
167
} else if (!empty($options['showsql'])) {
168
    $fixtables = array();
169
 
170
    foreach ($DB->get_tables(false) as $table) {
171
        $columns = $DB->get_columns($table, false);
172
        $size = $generator->guess_antelope_row_size($columns);
173
        $format = $DB->get_row_format($table);
174
        if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
175
            continue;
176
        }
177
        if ($format === 'Compact' or $format === 'Redundant') {
178
            $fixtables[$table] = $table;
179
        }
180
    }
181
    if (!$fixtables) {
182
        echo "No changes necessary\n";
183
        exit(0);
184
    }
185
 
186
    echo "Copy the following SQL statements and execute them using account with SUPER privilege:\n\n";
187
    echo "USE $database;\n";
188
    echo "SET SESSION sql_mode=STRICT_ALL_TABLES;\n";
189
    echo "SET GLOBAL innodb_file_per_table=1;\n";
190
    echo "SET GLOBAL innodb_file_format=Barracuda;\n";
191
    foreach ($fixtables as $table) {
192
        echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
193
    }
194
    echo "\n";
195
    exit(0);
196
 
197
} else {
198
    echo $help;
199
    die;
200
}
201
 
202