1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +01:00

Add "persistence" types (data, cache, or index) to tables, and tweak what "storage dump" dumps

Summary:
Ref T13000. This marks each table as either "data" (normal data), "cache" (automatically rebuilt, no need to ever dump) or "index" (can be manually rebuilt).

By default, `bin/storage dump` dumps data and index tables, but not cache tables.

With `--no-indexes`, it dumps only data tables. Indexes can be rebuilt after a restore with `bin/search index --all ...`.

Test Plan:
  - Ran `--no-indexes` and normal dumps with `--trace`, verified that cache and index (former case) or cache only (latter case) tables were dumped with `--no-data`.
  - Verified dump has the same number of `CREATE TABLE` statements as before the changes.
  - Reviewed persistence tags in the web UI (note Ferret engine tables are "Index"):

{F5210886}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13000

Differential Revision: https://secure.phabricator.com/D18682
This commit is contained in:
epriestley 2017-10-04 10:51:29 -07:00
parent 02e1440ef2
commit c767c971ca
8 changed files with 138 additions and 9 deletions

View file

@ -30,6 +30,9 @@ final class PhabricatorCacheSchemaSpec extends PhabricatorConfigSchemaSpec {
'key_ttl' => array( 'key_ttl' => array(
'columns' => array('cacheExpires'), 'columns' => array('cacheExpires'),
), ),
),
array(
'persistence' => PhabricatorConfigTableSchema::PERSISTENCE_CACHE,
)); ));
} }

View file

@ -261,6 +261,7 @@ final class PhabricatorConfigDatabaseStatusController
$this->renderAttr( $this->renderAttr(
$table->getCollation(), $table->getCollation(),
$table->hasIssue($collation_issue)), $table->hasIssue($collation_issue)),
$table->getPersistenceTypeDisplayName(),
); );
} }
@ -270,12 +271,14 @@ final class PhabricatorConfigDatabaseStatusController
null, null,
pht('Table'), pht('Table'),
pht('Collation'), pht('Collation'),
pht('Persistence'),
)) ))
->setColumnClasses( ->setColumnClasses(
array( array(
null, null,
'wide pri', 'wide pri',
null, null,
null,
)); ));
$title = $database_name; $title = $database_name;

View file

@ -338,6 +338,8 @@ final class PhabricatorConfigSchemaQuery extends Phobject {
$comp_table->addKey($comp_key); $comp_table->addKey($comp_key);
} }
$comp_table->setPersistenceType($expect_table->getPersistenceType());
$comp_database->addTable($comp_table); $comp_database->addTable($comp_table);
} }
$comp_server->addDatabase($comp_database); $comp_server->addDatabase($comp_database);

View file

@ -56,36 +56,52 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
} }
protected function buildFerretIndexSchema(PhabricatorFerretEngine $engine) { protected function buildFerretIndexSchema(PhabricatorFerretEngine $engine) {
$index_options = array(
'persistence' => PhabricatorConfigTableSchema::PERSISTENCE_INDEX,
);
$this->buildRawSchema( $this->buildRawSchema(
$engine->getApplicationName(), $engine->getApplicationName(),
$engine->getDocumentTableName(), $engine->getDocumentTableName(),
$engine->getDocumentSchemaColumns(), $engine->getDocumentSchemaColumns(),
$engine->getDocumentSchemaKeys()); $engine->getDocumentSchemaKeys(),
$index_options);
$this->buildRawSchema( $this->buildRawSchema(
$engine->getApplicationName(), $engine->getApplicationName(),
$engine->getFieldTableName(), $engine->getFieldTableName(),
$engine->getFieldSchemaColumns(), $engine->getFieldSchemaColumns(),
$engine->getFieldSchemaKeys()); $engine->getFieldSchemaKeys(),
$index_options);
$this->buildRawSchema( $this->buildRawSchema(
$engine->getApplicationName(), $engine->getApplicationName(),
$engine->getNgramsTableName(), $engine->getNgramsTableName(),
$engine->getNgramsSchemaColumns(), $engine->getNgramsSchemaColumns(),
$engine->getNgramsSchemaKeys()); $engine->getNgramsSchemaKeys(),
$index_options);
$this->buildRawSchema( $this->buildRawSchema(
$engine->getApplicationName(), $engine->getApplicationName(),
$engine->getCommonNgramsTableName(), $engine->getCommonNgramsTableName(),
$engine->getCommonNgramsSchemaColumns(), $engine->getCommonNgramsSchemaColumns(),
$engine->getCommonNgramsSchemaKeys()); $engine->getCommonNgramsSchemaKeys(),
$index_options);
} }
protected function buildRawSchema( protected function buildRawSchema(
$database_name, $database_name,
$table_name, $table_name,
array $columns, array $columns,
array $keys) { array $keys,
array $options = array()) {
PhutilTypeSpec::checkMap(
$options,
array(
'persistence' => 'optional string',
));
$database = $this->getDatabase($database_name); $database = $this->getDatabase($database_name);
$table = $this->newTable($table_name); $table = $this->newTable($table_name);
@ -144,6 +160,11 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
$table->addKey($key); $table->addKey($key);
} }
$persistence_type = idx($options, 'persistence');
if ($persistence_type !== null) {
$table->setPersistenceType($persistence_type);
}
$database->addTable($table); $database->addTable($table);
} }

View file

@ -7,6 +7,11 @@ final class PhabricatorConfigTableSchema
private $engine; private $engine;
private $columns = array(); private $columns = array();
private $keys = array(); private $keys = array();
private $persistenceType = self::PERSISTENCE_DATA;
const PERSISTENCE_DATA = 'data';
const PERSISTENCE_CACHE = 'cache';
const PERSISTENCE_INDEX = 'index';
public function addColumn(PhabricatorConfigColumnSchema $column) { public function addColumn(PhabricatorConfigColumnSchema $column) {
$key = $column->getName(); $key = $column->getName();
@ -45,6 +50,27 @@ final class PhabricatorConfigTableSchema
return idx($this->getKeys(), $key); return idx($this->getKeys(), $key);
} }
public function setPersistenceType($persistence_type) {
$this->persistenceType = $persistence_type;
return $this;
}
public function getPersistenceType() {
return $this->persistenceType;
}
public function getPersistenceTypeDisplayName() {
$map = array(
self::PERSISTENCE_DATA => pht('Data'),
self::PERSISTENCE_CACHE => pht('Cache'),
self::PERSISTENCE_INDEX => pht('Index'),
);
$type = $this->getPersistenceType();
return idx($map, $type, $type);
}
protected function getSubschemata() { protected function getSubschemata() {
// NOTE: Keys and columns may have the same name, so make sure we return // NOTE: Keys and columns may have the same name, so make sure we return
// everything. // everything.

View file

@ -21,6 +21,9 @@ final class DifferentialSchemaSpec extends PhabricatorConfigSchemaSpec {
'dateCreated' => array( 'dateCreated' => array(
'columns' => array('dateCreated'), 'columns' => array('dateCreated'),
), ),
),
array(
'persistence' => PhabricatorConfigTableSchema::PERSISTENCE_CACHE,
)); ));
$this->buildRawSchema( $this->buildRawSchema(

View file

@ -145,6 +145,24 @@ present a risk. If you restrict access to the Phabricator host or database, you
should also restrict access to the backups. should also restrict access to the backups.
Skipping Indexes
================
By default, `bin/storage dump` does not dump all of the data in the database:
it skips some caches which can be rebuilt automatically and do not need to be
backed up. Some of these caches are very large, so the size of the dump may
be significantly smaller than the size of the databases.
If you have a large amount of data, you can specify `--no-indexes` when taking
a database dump to skip additional tables which contain search indexes. This
will reduce the size (and increase the speed) of the backup. This is an
advanced option which most installs will not benefit from.
This index data can be rebuilt after a restore, but will not be rebuilt
automatically. If you choose to use this flag, you must manually rebuild
indexes after a restore (for details, see ((reindex))).
Next Steps Next Steps
========== ==========

View file

@ -30,6 +30,13 @@ final class PhabricatorStorageManagementDumpWorkflow
'With __--output__, write a compressed file to disk instead '. 'With __--output__, write a compressed file to disk instead '.
'of a plaintext file.'), 'of a plaintext file.'),
), ),
array(
'name' => 'no-indexes',
'help' => pht(
'Do not dump data in rebuildable index tables. This means '.
'backups are smaller and faster, but you will need to manually '.
'rebuild indexes after performing a restore.'),
),
array( array(
'name' => 'overwrite', 'name' => 'overwrite',
'help' => pht( 'help' => pht(
@ -49,6 +56,8 @@ final class PhabricatorStorageManagementDumpWorkflow
$console = PhutilConsole::getConsole(); $console = PhutilConsole::getConsole();
$with_indexes = !$args->getArg('no-indexes');
$applied = $api->getAppliedPatches(); $applied = $api->getAppliedPatches();
if ($applied === null) { if ($applied === null) {
$namespace = $api->getNamespace(); $namespace = $api->getNamespace();
@ -65,18 +74,58 @@ final class PhabricatorStorageManagementDumpWorkflow
$ref = $api->getRef(); $ref = $api->getRef();
$ref_key = $ref->getRefKey(); $ref_key = $ref->getRefKey();
$schemata_map = id(new PhabricatorConfigSchemaQuery()) $schemata_query = id(new PhabricatorConfigSchemaQuery())
->setAPIs(array($api)) ->setAPIs(array($api))
->setRefs(array($ref)) ->setRefs(array($ref));
->loadActualSchemata();
$schemata = $schemata_map[$ref_key]; $actual_map = $schemata_query->loadActualSchemata();
$expect_map = $schemata_query->loadExpectedSchemata();
$schemata = $actual_map[$ref_key];
$expect = $expect_map[$ref_key];
$targets = array(); $targets = array();
foreach ($schemata->getDatabases() as $database_name => $database) { foreach ($schemata->getDatabases() as $database_name => $database) {
$expect_database = $expect->getDatabase($database_name);
foreach ($database->getTables() as $table_name => $table) { foreach ($database->getTables() as $table_name => $table) {
// NOTE: It's possible for us to find tables in these database which
// we don't expect to be there. For example, an older version of
// Phabricator may have had a table that was later dropped. We assume
// these are data tables and always dump them, erring on the side of
// caution.
$persistence = PhabricatorConfigTableSchema::PERSISTENCE_DATA;
if ($expect_database) {
$expect_table = $expect_database->getTable($table_name);
if ($expect_table) {
$persistence = $expect_table->getPersistenceType();
}
}
switch ($persistence) {
case PhabricatorConfigTableSchema::PERSISTENCE_CACHE:
// When dumping tables, leave the data in cache tables in the
// database. This will be automatically rebuild after the data
// is restored and does not need to be persisted in backups.
$with_data = false;
break;
case PhabricatorConfigTableSchema::PERSISTENCE_INDEX:
// When dumping tables, leave index data behind of the caller
// specified "--no-indexes". These tables can be rebuilt manually
// from other tables, but do not rebuild automatically.
$with_data = $with_indexes;
break;
case PhabricatorConfigTableSchema::PERSISTENCE_DATA:
default:
$with_data = true;
break;
}
$targets[] = array( $targets[] = array(
'database' => $database_name, 'database' => $database_name,
'table' => $table_name, 'table' => $table_name,
'data' => $with_data,
); );
} }
} }
@ -147,6 +196,10 @@ final class PhabricatorStorageManagementDumpWorkflow
foreach ($targets as $target) { foreach ($targets as $target) {
$target_argv = $argv; $target_argv = $argv;
if (!$target['data']) {
$target_argv[] = '--no-data';
}
if ($has_password) { if ($has_password) {
$commands[] = csprintf( $commands[] = csprintf(
'mysqldump -p%P %Ls -- %R %R', 'mysqldump -p%P %Ls -- %R %R',