~ubuntu-branches/ubuntu/lucid/phpmyadmin/lucid

« back to all changes in this revision

Viewing changes to libraries/replication.inc.php

  • Committer: Bazaar Package Importer
  • Author(s): Michal Čihař
  • Date: 2010-03-08 15:25:00 UTC
  • mfrom: (1.2.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20100308152500-6e8hmuqc5co39de5
Tags: 4:3.3.0-1
* New upstream version.
* Rediff debian/patches.
* Fix permissions on mediawiki export extension.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/* vim: set expandtab sw=4 ts=4 sts=4: */
 
3
/**
 
4
 *
 
5
 * @version $Id: replication.inc.php 13171 2009-12-24 12:33:04Z lem9 $
 
6
 * @package phpMyAdmin
 
7
 */
 
8
 
 
9
if (! defined('PHPMYADMIN')) {
 
10
    exit;
 
11
}
 
12
 
 
13
/**
 
14
 * get master replication from server
 
15
 */
 
16
$server_master_replication = PMA_DBI_fetch_result('SHOW MASTER STATUS'); 
 
17
 
 
18
/**
 
19
 * get slave replication from server
 
20
 */
 
21
$server_slave_replication = PMA_DBI_fetch_result('SHOW SLAVE STATUS');
 
22
 
 
23
/** 
 
24
 * replication types
 
25
 */
 
26
$replication_types = array('master', 'slave');
 
27
 
 
28
 
 
29
/**
 
30
 * define variables for master status
 
31
 */
 
32
$master_variables = array(
 
33
    'File',
 
34
    'Position',
 
35
    'Binlog_Do_DB',
 
36
    'Binlog_Ignore_DB',
 
37
);
 
38
 
 
39
/**
 
40
 * Define variables for slave status
 
41
 */
 
42
$slave_variables  = array(
 
43
    'Slave_IO_State',
 
44
    'Master_Host',
 
45
    'Master_User',
 
46
    'Master_Port',
 
47
    'Connect_Retry',
 
48
    'Master_Log_File',
 
49
    'Read_Master_Log_Pos',
 
50
    'Relay_Log_File',
 
51
    'Relay_Log_Pos',
 
52
    'Relay_Master_Log_File',
 
53
    'Slave_IO_Running',
 
54
    'Slave_SQL_Running',
 
55
    'Replicate_Do_DB',
 
56
    'Replicate_Ignore_DB',
 
57
    'Replicate_Do_Table',
 
58
    'Replicate_Ignore_Table',
 
59
    'Replicate_Wild_Do_Table',
 
60
    'Replicate_Wild_Ignore_Table',
 
61
    'Last_Errno',
 
62
    'Last_Error',
 
63
    'Skip_Counter',
 
64
    'Exec_Master_Log_Pos',
 
65
    'Relay_Log_Space',
 
66
    'Until_Condition',
 
67
    'Until_Log_File',
 
68
    'Until_Log_Pos',
 
69
    'Master_SSL_Allowed',
 
70
    'Master_SSL_CA_File',
 
71
    'Master_SSL_CA_Path',
 
72
    'Master_SSL_Cert',
 
73
    'Master_SSL_Cipher',
 
74
    'Master_SSL_Key',
 
75
    'Seconds_Behind_Master',
 
76
);
 
77
/**
 
78
 * define important variables, which need to be watched for correct running of replication in slave mode
 
79
 *
 
80
 * @usedby PMA_replication_print_status_table()
 
81
 */
 
82
// TODO change to regexp or something, to allow for negative match. To e.g. highlight 'Last_Error'
 
83
//
 
84
$slave_variables_alerts = array(
 
85
    'Slave_IO_Running' => 'No',
 
86
    'Slave_SQL_Running' => 'No',
 
87
);
 
88
$slave_variables_oks = array(
 
89
    'Slave_IO_Running' => 'Yes',
 
90
    'Slave_SQL_Running' => 'Yes',
 
91
);
 
92
 
 
93
$serverid = time();
 
94
 
 
95
// check which replication is available and set $server_{master/slave}_status and assign values
 
96
foreach ($replication_types as $type) {
 
97
    if (count(${"server_{$type}_replication"}) > 0) {
 
98
        ${"server_{$type}_status"} = true;
 
99
    } else {
 
100
        ${"server_{$type}_status"} = false;
 
101
    }
 
102
    if (${"server_{$type}_status"}) {
 
103
        if ($type == "master") {
 
104
            ${"server_{$type}_Do_DB"} = explode(",", $server_master_replication[0]["Binlog_Do_DB"]);
 
105
            ${"server_{$type}_Ignore_DB"} = explode(",", $server_master_replication[0]["Binlog_Ignore_DB"]);
 
106
        } elseif ($type == "slave") {
 
107
            ${"server_{$type}_Do_DB"} = explode(",", $server_slave_replication[0]["Replicate_Do_DB"]);
 
108
            ${"server_{$type}_Ignore_DB"} = explode(",", $server_slave_replication[0]["Replicate_Ignore_DB"]);
 
109
 
 
110
            ${"server_{$type}_Do_Table"} = explode(",", $server_slave_replication[0]["Replicate_Do_Table"]);
 
111
            ${"server_{$type}_Ignore_Table"} = explode(",", $server_slave_replication[0]["Replicate_Ignore_Table"]);
 
112
 
 
113
            ${"server_{$type}_Wild_Do_Table"} = explode(",", $server_slave_replication[0]["Replicate_Wild_Do_Table"]);
 
114
            ${"server_{$type}_Wild_Ignore_Table"} = explode(",", $server_slave_replication[0]["Replicate_Wild_Ignore_Table"]);
 
115
        }
 
116
    }
 
117
}
 
118
 
 
119
 
 
120
/**
 
121
 * @param $string - 
 
122
 * @param $table - 
 
123
 * @return 
 
124
 */
 
125
function PMA_replication_strout($string, $table = false) {
 
126
    $list = explode(".", $string);
 
127
 
 
128
    return $list[(int)$table];
 
129
}
 
130
/**
 
131
 * @param String $action - possible values: START or STOP
 
132
 * @param String $control - default: null, possible values: SQL_THREAD or IO_THREAD or null. If it is set to null, it controls both SQL_THREAD and IO_THREAD
 
133
 * @param mixed  $link   - mysql link
 
134
 *
 
135
 * @return mixed output of PMA_DBI_try_query
 
136
 */
 
137
function PMA_replication_slave_control($action, $control = null, $link = null) {
 
138
    $action = strtoupper($action);
 
139
    $control = strtoupper($control);
 
140
 
 
141
    if ($action != "START" && $action != "STOP") {
 
142
        return -1;
 
143
    }
 
144
    if ($control != "SQL_THREAD" && $control != "IO_THREAD" && $control != null) {
 
145
        return -1;
 
146
    }
 
147
 
 
148
    return PMA_DBI_try_query($action . " SLAVE " . $control . ";", $link);
 
149
}
 
150
/**
 
151
 * @param String $user - replication user on master
 
152
 * @param String $password - password for the user
 
153
 * @param String $host - master's hostname or IP
 
154
 * @param int $port - port, where mysql is running
 
155
 * @param array $pos - position of mysql replication, array should contain fields File and Position
 
156
 * @param boolean $stop - shall we stop slave?
 
157
 * @param boolean $start - shall we start slave?
 
158
 * @param mixed $link - mysql link
 
159
 *
 
160
 * @return output of CHANGE MASTER mysql command
 
161
 */
 
162
function PMA_replication_slave_change_master($user, $password, $host, $port, $pos, $stop = true, $start = true, $link = null) {
 
163
    if ($stop) {
 
164
        PMA_replication_slave_control("STOP", null, $link);
 
165
    }
 
166
 
 
167
    $out = PMA_DBI_try_query('CHANGE MASTER TO ' .
 
168
        'MASTER_HOST=\'' . $host . '\',' .
 
169
        'MASTER_PORT=' . ($port * 1) . ',' .
 
170
        'MASTER_USER=\'' . $user . '\',' .
 
171
        'MASTER_PASSWORD=\'' . $password . '\',' .
 
172
        'MASTER_LOG_FILE=\'' . $pos["File"] . '\',' .
 
173
        'MASTER_LOG_POS=' . $pos["Position"] . ';', $link);
 
174
 
 
175
    if ($start) {
 
176
        PMA_replication_slave_control("START", null, $link);
 
177
    }
 
178
 
 
179
    return $out;
 
180
}
 
181
 
 
182
/**
 
183
 * This function provides connection to remote mysql server
 
184
 *
 
185
 * @param String $user - mysql username
 
186
 * @param String $password - password for the user
 
187
 * @param String $host - mysql server's hostname or IP
 
188
 * @param int $port - mysql remote port
 
189
 * @param String $socket - path to unix socket
 
190
 * 
 
191
 * @return mixed $link mysql link on success
 
192
 */
 
193
function PMA_replication_connect_to_master($user, $password, $host = null, $port = null, $socket = null) {
 
194
    $server = array();
 
195
    $server["host"] = $host;
 
196
    $server["port"] = $port;
 
197
    $server["socket"] = $socket;
 
198
 
 
199
    // 5th parameter set to true means that it's an auxiliary connection 
 
200
    // and we must not go back to login page if it fails
 
201
    return PMA_DBI_connect($user, $password, false, $server, true);
 
202
}
 
203
/**
 
204
 * @param $link - mysql link
 
205
 *
 
206
 * @return array - containing File and Position in MySQL replication on master server, useful for PMA_replication_slave_change_master
 
207
 */
 
208
function PMA_replication_slave_bin_log_master($link = null) {
 
209
    $data = PMA_DBI_fetch_result('SHOW MASTER STATUS', null, null, $link);
 
210
    $output = array();
 
211
 
 
212
    if (! empty($data)) {
 
213
        $output["File"] = $data[0]["File"];
 
214
        $output["Position"] = $data[0]["Position"];
 
215
    }
 
216
    return $output;
 
217
}
 
218
 
 
219
/**
 
220
 * Get list of replicated databases on master server
 
221
 * 
 
222
 * @param mixed mysql link
 
223
 *
 
224
 * @return array array of replicated databases
 
225
 */
 
226
 
 
227
function PMA_replication_master_replicated_dbs($link = null) {
 
228
    $data = PMA_DBI_fetch_result('SHOW MASTER STATUS', null, null, $link); // let's find out, which databases are replicated
 
229
 
 
230
    $do_db     = array();
 
231
    $ignore_db = array();
 
232
 
 
233
    if (! empty($data[0]['Binlog_Do_DB'])) {
 
234
        $do_db     = explode(',', $data[0]['Binlog_Do_DB']);
 
235
    }
 
236
    if (! empty($data[0]['Binlog_Ignore_DB'])) {
 
237
        $ignore_db = explode(',', $data[0]['Binlog_Ignore_DB']);
 
238
    }
 
239
 
 
240
    $tmp_alldbs = PMA_DBI_query('SHOW DATABASES;', $link);
 
241
    while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) {
 
242
        if ($tmp_row[0] == 'information_schema')
 
243
            continue;
 
244
        if (count($do_db) == 0) {
 
245
            if (array_search($tmp_row[0], $ignore_db) !== false) {
 
246
                continue;
 
247
            }
 
248
            $dblist[] = $tmp_row[0];
 
249
 
 
250
        } else {
 
251
            if (array_search($tmp_row[0], $do_db) !== false) {
 
252
                $dblist[] = $tmp_row[0];
 
253
            }
 
254
        }         
 
255
    } // end while
 
256
 
 
257
    return $link;
 
258
}
 
259
/**
 
260
 * This function provides synchronization of structure and data between two mysql servers. 
 
261
 * TODO: improve code sharing between the function and synchronization
 
262
 *
 
263
 * @param String $db - name of database, which should be synchronized
 
264
 * @param mixed $src_link - link of source server, note: if the server is current PMA server, use null
 
265
 * @param mixed $trg_link - link of target server, note: if the server is current PMA server, use null
 
266
 * @param boolean $data - if true, then data will be copied as well
 
267
 */
 
268
 
 
269
function PMA_replication_synchronize_db($db, $src_link, $trg_link, $data = true) {
 
270
    $src_db = $trg_db = $db;
 
271
 
 
272
    $src_connection = PMA_DBI_select_db($src_db, $src_link);
 
273
    $trg_connection = PMA_DBI_select_db($trg_db, $trg_link);
 
274
 
 
275
    $src_tables = PMA_DBI_get_tables($src_db, $src_link);
 
276
    $source_tables_num = sizeof($src_tables);
 
277
 
 
278
    $trg_tables = PMA_DBI_get_tables($trg_db, $trg_link);
 
279
    $target_tables_num = sizeof($trg_tables);
 
280
 
 
281
    /**
 
282
     * initializing arrays to save table names 
 
283
     */                                      
 
284
    $unmatched_num_src = 0;
 
285
    $source_tables_uncommon = array();
 
286
    $unmatched_num_trg = 0;
 
287
    $target_tables_uncommon = array();
 
288
    $matching_tables = array();
 
289
    $matching_tables_num = 0;
 
290
 
 
291
    /**
 
292
     * Criterion for matching tables is just their names.
 
293
     * Finding the uncommon tables for the source database
 
294
     * BY comparing the matching tables with all the tables in the source database
 
295
     */                                                                           
 
296
    PMA_getMatchingTables($trg_tables, $src_tables, $matching_tables, $source_tables_uncommon);
 
297
 
 
298
    /**
 
299
     * Finding the uncommon tables for the target database
 
300
     * BY comparing the matching tables with all the tables in the target database
 
301
     */
 
302
    PMA_getNonMatchingTargetTables($trg_tables, $matching_tables, $target_tables_uncommon);
 
303
 
 
304
    /**
 
305
     * 
 
306
     * Comparing Data In the Matching Tables 
 
307
     * It is assumed that the matching tables are structurally 
 
308
     * and typely exactly the same  
 
309
     */
 
310
    $fields_num = array();
 
311
    $matching_tables_fields = array();
 
312
    $matching_tables_keys   = array();
 
313
    $insert_array = array(array(array()));
 
314
    $update_array = array(array(array()));
 
315
    $delete_array = array();
 
316
    $row_count = array();
 
317
    $uncommon_tables_fields = array();
 
318
    $matching_tables_num = sizeof($matching_tables);
 
319
 
 
320
    for ($i = 0; $i < sizeof($matching_tables); $i++) {
 
321
        PMA_dataDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $matching_tables_fields, $update_array, $insert_array,
 
322
            $delete_array, $fields_num, $i, $matching_tables_keys);
 
323
    }
 
324
    for ($j = 0; $j < sizeof($source_tables_uncommon); $j++) {
 
325
        PMA_dataDiffInUncommonTables($source_tables_uncommon, $src_db, $src_link, $j, $row_count);
 
326
    }  
 
327
 
 
328
    /**
 
329
     * INTEGRATION OF STRUCTURE DIFFERENCE CODE
 
330
     *
 
331
     */
 
332
    $source_columns = array();
 
333
    $target_columns = array();
 
334
    $alter_str_array = array(array());
 
335
    $add_column_array = array(array());
 
336
    $uncommon_columns = array(); 
 
337
    $target_tables_keys = array();
 
338
    $source_indexes = array();
 
339
    $target_indexes = array();
 
340
    $add_indexes_array = array();
 
341
    $remove_indexes_array = array();
 
342
    $criteria = array('Field', 'Type', 'Null', 'Collation', 'Key', 'Default', 'Comment');
 
343
 
 
344
    for ($counter = 0; $counter < $matching_tables_num; $counter++) {
 
345
        PMA_structureDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_columns,
 
346
            $target_columns, $alter_str_array, $add_column_array, $uncommon_columns, $criteria, $target_tables_keys, $counter);    
 
347
 
 
348
        PMA_indexesDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_indexes, $target_indexes,
 
349
            $add_indexes_array, $alter_indexes_array,$remove_indexes_array, $counter);      
 
350
    } 
 
351
 
 
352
    $matching_table_data_diff = array();
 
353
    $matching_table_structure_diff = array();
 
354
    $uncommon_table_structure_diff = array();
 
355
    $uncommon_table_data_diff = array();
 
356
    $uncommon_tables = $source_tables_uncommon;
 
357
 
 
358
    /**
 
359
     * Generating Create Table query for all the non-matching tables present in Source but not in Target and populating tables.  
 
360
     */   
 
361
    for($q = 0; $q < sizeof($source_tables_uncommon); $q++) { 
 
362
        if (isset($uncommon_tables[$q])) {
 
363
            PMA_createTargetTables($src_db, $trg_db, $src_link, $trg_link, $source_tables_uncommon, $q, $uncommon_tables_fields, false);
 
364
        }
 
365
        if (isset($row_count[$q]) && $data) {
 
366
            PMA_populateTargetTables($src_db, $trg_db, $src_link, $trg_link, $source_tables_uncommon, $q, $uncommon_tables_fields, false);    
 
367
        }
 
368
    }
 
369
}
 
370
?>