Skip to content

Commit 5a0b739

Browse files
author
epriestley
committed
Give bin/storage some replica-aware options
Summary: Fixes T10758. - Adds a "--host" flag. If you specify this, we read your cluster config. This lets you dump from a replica. - Adds a "--for-replica" flag to `storage dump`. This makes `mysqldump` include a `CHANGE MASTER ...` statement in the output, which is useful when setting up a replica for the first time. Test Plan: - Dumped master and replica cluster databases. - Dumped non-cluster databases. - Ran various other commands (help, status, etc). Reviewers: chad Reviewed By: chad Maniphest Tasks: T10758 Differential Revision: https://secure.phabricator.com/D15714
1 parent 1b2b84c commit 5a0b739

File tree

3 files changed

+89
-24
lines changed

3 files changed

+89
-24
lines changed

scripts/sql/manage_storage.php

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
'help' => pht(
3131
'Do not prompt before performing dangerous operations.'),
3232
),
33+
array(
34+
'name' => 'host',
35+
'param' => 'hostname',
36+
'help' => pht(
37+
'Connect to __host__ instead of the default host.'),
38+
),
3339
array(
3440
'name' => 'user',
3541
'short' => 'u',
@@ -75,10 +81,37 @@
7581
// First, test that the Phabricator configuration is set up correctly. After
7682
// we know this works we'll test any administrative credentials specifically.
7783

78-
$ref = PhabricatorDatabaseRef::getMasterDatabaseRef();
79-
if (!$ref) {
80-
throw new Exception(
81-
pht('No database master is configured.'));
84+
$host = $args->getArg('host');
85+
if (strlen($host)) {
86+
$ref = null;
87+
88+
$refs = PhabricatorDatabaseRef::getLiveRefs();
89+
90+
// Include the master in case the user is just specifying a redundant
91+
// "--host" flag for no reason and does not actually have a database
92+
// cluster configured.
93+
$refs[] = PhabricatorDatabaseRef::getMasterDatabaseRef();
94+
95+
foreach ($refs as $possible_ref) {
96+
if ($possible_ref->getHost() == $host) {
97+
$ref = $possible_ref;
98+
break;
99+
}
100+
}
101+
102+
if (!$ref) {
103+
throw new PhutilArgumentUsageException(
104+
pht(
105+
'There is no configured database on host "%s". This command can '.
106+
'only interact with configured databases.',
107+
$host));
108+
}
109+
} else {
110+
$ref = PhabricatorDatabaseRef::getMasterDatabaseRef();
111+
if (!$ref) {
112+
throw new Exception(
113+
pht('No database master is configured.'));
114+
}
82115
}
83116

84117
$default_user = $ref->getUser();

src/docs/user/cluster/cluster_databases.diviner

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,15 @@ safely pull dumps from a replica instead of the master. This operation can
296296
be slow, so offloading it to a replica can make the performance of the master
297297
more consistent.
298298

299-
To dump from a replica, wait for this TODO to be resolved and then do whatever
300-
it says to do:
301-
302-
TODO: Make `bin/storage dump` replica-aware. See T10758.
299+
To dump from a replica, you can use `bin/storage dump --host <host>` to
300+
control which host the command connects to. (You may still want to execute
301+
this command //from// that host, to avoid sending the whole dump over the
302+
network).
303+
304+
With the `--for-replica` flag, the `bin/storage dump` command creates dumps
305+
with `--dump-slave`, which includes a `CHANGE MASTER` statement in the output.
306+
This may be helpful when initially setting up new replicas, as it can make it
307+
easier to change the binlog coordinates to the correct position for the dump.
303308

304309
With recent versions of MySQL, it is also possible to configure a //delayed//
305310
replica which intentionally lags behind the master (say, by 12 hours). In the

src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,20 @@ protected function didConstruct() {
77
$this
88
->setName('dump')
99
->setExamples('**dump** [__options__]')
10-
->setSynopsis(pht('Dump all data in storage to stdout.'));
10+
->setSynopsis(pht('Dump all data in storage to stdout.'))
11+
->setArguments(
12+
array(
13+
array(
14+
'name' => 'for-replica',
15+
'help' => pht(
16+
'Add __--dump-slave__ to the __mysqldump__ command, '.
17+
'generating a CHANGE MASTER statement in the output.'),
18+
),
19+
));
1120
}
1221

1322
public function didExecute(PhutilArgumentParser $args) {
14-
$api = $this->getAPI();
23+
$api = $this->getAPI();
1524
$patches = $this->getPatches();
1625

1726
$console = PhutilConsole::getConsole();
@@ -33,26 +42,44 @@ public function didExecute(PhutilArgumentParser $args) {
3342

3443
list($host, $port) = $this->getBareHostAndPort($api->getHost());
3544

36-
$flag_password = '';
3745
$password = $api->getPassword();
3846
if ($password) {
3947
if (strlen($password->openEnvelope())) {
40-
$flag_password = csprintf('-p%P', $password);
48+
$has_password = true;
4149
}
4250
}
4351

44-
$flag_port = $port
45-
? csprintf('--port %d', $port)
46-
: '';
47-
48-
return phutil_passthru(
49-
'mysqldump --hex-blob --single-transaction --default-character-set=utf8 '.
50-
'-u %s %C -h %s %C --databases %Ls',
51-
$api->getUser(),
52-
$flag_password,
53-
$host,
54-
$flag_port,
55-
$databases);
52+
$argv = array();
53+
$argv[] = '--hex-blob';
54+
$argv[] = '--single-transaction';
55+
$argv[] = '--default-character-set=utf8';
56+
57+
if ($args->getArg('for-replica')) {
58+
$argv[] = '--dump-slave';
59+
}
60+
61+
$argv[] = '-u';
62+
$argv[] = $api->getUser();
63+
$argv[] = '-h';
64+
$argv[] = $host;
65+
66+
if ($port) {
67+
$argv[] = '--port';
68+
$argv[] = $port;
69+
}
70+
71+
$argv[] = '--databases';
72+
foreach ($databases as $database) {
73+
$argv[] = $database;
74+
}
75+
76+
if ($has_password) {
77+
$err = phutil_passthru('mysqldump -p%P %Ls', $password, $argv);
78+
} else {
79+
$err = phutil_passthru('mysqldump %Ls', $argv);
80+
}
81+
82+
return $err;
5683
}
5784

5885
}

0 commit comments

Comments
 (0)