#At file:///home/marty/MySQL/mysql-5.1-telco-6.2/
3038 Martin Skold 2009-11-25
Bug#48005 ndb backup / restore does not restore the auto_increment: Restoring auto_increment values directly from SYSTAB_0
modified:
mysql-test/suite/ndb/r/ndb_restore.result
mysql-test/suite/ndb/t/ndb_restore.test
storage/ndb/include/ndbapi/NdbDictionary.hpp
storage/ndb/src/ndbapi/NdbDictionary.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
storage/ndb/tools/restore/Restore.cpp
storage/ndb/tools/restore/Restore.hpp
storage/ndb/tools/restore/consumer_printer.cpp
storage/ndb/tools/restore/consumer_restore.cpp
storage/ndb/tools/restore/consumer_restore.hpp
storage/ndb/tools/restore/restore_main.cpp
=== modified file 'mysql-test/suite/ndb/r/ndb_restore.result'
--- a/mysql-test/suite/ndb/r/ndb_restore.result 2009-09-08 11:24:03 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore.result 2009-11-25 12:37:14 +0000
@@ -510,3 +510,21 @@ epoch
select epoch > (1 << 32) from mysql.ndb_apply_status where server_id=0;
epoch > (1 << 32)
1
+create table t1 (a int not null primary key auto_increment, b int) auto_increment=200
+engine=ndb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=ndbcluster AUTO_INCREMENT=200 DEFAULT CHARSET=latin1
+drop table t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=ndbcluster AUTO_INCREMENT=200 DEFAULT CHARSET=latin1
+drop table t1;
=== modified file 'mysql-test/suite/ndb/t/ndb_restore.test'
--- a/mysql-test/suite/ndb/t/ndb_restore.test 2009-09-08 11:24:03 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore.test 2009-11-25 12:37:14 +0000
@@ -454,3 +454,16 @@ select epoch > (1 << 32) from mysql.ndb_
# Bug #33040 ndb_restore crashes with --print_log
#
--exec $NDB_TOOLS_DIR/ndb_restore --print_log -b 1 -n 1 $MYSQL_TEST_DIR/std_data/ndb_backup50 >> $NDB_TOOLS_OUTPUT
+
+#
+# Bug#48005 ndb backup / restore does not restore the auto_increment
+#
+create table t1 (a int not null primary key auto_increment, b int) auto_increment=200
+engine=ndb;
+show create table t1;
+--source include/ndb_backup.inc
+drop table t1;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -m -r --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 2 -r --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+show create table t1;
+drop table t1;
=== modified file 'storage/ndb/include/ndbapi/NdbDictionary.hpp'
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp 2009-10-07 02:21:54 +0000
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp 2009-11-25 12:37:14 +0000
@@ -734,6 +734,11 @@ public:
int getNoOfColumns() const;
/**
+ * Get number of auto_increment columns in the table
+ */
+ int getNoOfAutoIncrementColumns() const;
+
+ /**
* Get number of primary keys in the table
*/
int getNoOfPrimaryKeys() const;
=== modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp 2009-10-07 02:21:54 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp 2009-11-25 12:37:14 +0000
@@ -581,6 +581,11 @@ NdbDictionary::Table::getNoOfColumns() c
}
int
+NdbDictionary::Table::getNoOfAutoIncrementColumns() const {
+ return m_impl.m_noOfAutoIncColumns;
+}
+
+int
NdbDictionary::Table::getNoOfPrimaryKeys() const {
return m_impl.m_noOfKeys;
}
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-11-25 12:37:14 +0000
@@ -499,6 +499,7 @@ NdbTableImpl::init(){
m_noOfDistributionKeys= 0;
m_noOfBlobs= 0;
m_replicaCount= 0;
+ m_noOfAutoIncColumns = 0;
m_ndbrecord= 0;
m_pkMask= 0;
m_min_rows = 0;
@@ -788,6 +789,8 @@ NdbTableImpl::assign(const NdbTableImpl&
m_noOfBlobs = org.m_noOfBlobs;
m_replicaCount = org.m_replicaCount;
+ m_noOfAutoIncColumns = org.m_noOfAutoIncColumns;
+
m_id = org.m_id;
m_version = org.m_version;
m_status = org.m_status;
@@ -837,6 +840,9 @@ NdbTableImpl::computeAggregates()
m_noOfDiskColumns++;
col->m_keyInfoPos = ~0;
+
+ if (col->m_autoIncrement)
+ m_noOfAutoIncColumns++;
}
if (m_noOfDistributionKeys == m_noOfKeys) {
// all is none!
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-11-25 12:37:14 +0000
@@ -209,6 +209,7 @@ public:
if iterating over columns.
*/
Vector<NdbColumnImpl *> m_columns;
+ Uint32 m_noOfAutoIncColumns;
void computeAggregates();
int buildColumnHash();
=== modified file 'storage/ndb/tools/restore/Restore.cpp'
--- a/storage/ndb/tools/restore/Restore.cpp 2009-09-08 10:38:53 +0000
+++ b/storage/ndb/tools/restore/Restore.cpp 2009-11-25 12:37:14 +0000
@@ -347,8 +347,12 @@ RestoreMetaData::markSysTables()
strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_SCHEMA_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 )
-
- table->isSysTable = true;
+ {
+ table->m_isSysTable = true;
+ if (strcmp(tableName, "SYSTAB_0") == 0 ||
+ strcmp(tableName, "sys/def/SYSTAB_0") == 0)
+ table->m_isSYSTAB_0 = true;
+ }
}
for (i = 0; i < getNoOfTables(); i++) {
TableS* blobTable = allTables[i];
@@ -363,8 +367,8 @@ RestoreMetaData::markSysTables()
for (j = 0; j < getNoOfTables(); j++) {
TableS* table = allTables[j];
if (table->getTableId() == (Uint32) id1) {
- if (table->isSysTable)
- blobTable->isSysTable = true;
+ if (table->m_isSysTable)
+ blobTable->m_isSysTable = true;
blobTable->m_main_table = table;
blobTable->m_main_column_id = id2;
break;
@@ -509,7 +513,8 @@ TableS::TableS(Uint32 version, NdbTableI
m_max_auto_val= 0;
m_noOfRecords= 0;
backupVersion = version;
- isSysTable = false;
+ m_isSysTable = false;
+ m_isSYSTAB_0 = false;
m_main_table = NULL;
m_main_column_id = ~(Uint32)0;
@@ -1122,6 +1127,35 @@ void TableS::createAttr(NdbDictionary::C
m_variableAttribs.push_back(d);
} // TableS::createAttr
+bool
+TableS::get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const
+{
+ /*
+ Read current (highest) auto_increment value for
+ a table. Currently there can only be one per table.
+ The values are stored in sustable SYSTAB_0 as
+ {SYSKEY,NEXTID} values where SYSKEY (32-bit) is
+ the table_id and NEXTID (64-bit) is the next auto_increment
+ value in the sequence (note though that sequences of
+ values can have been fetched and that are cached in NdbAPI).
+ SYSTAB_0 can contain other data so we need to check that
+ the found SYSKEY value is a valid table_id (< 0x1000000).
+ */
+ AttributeData * attr_data = tuple.getData(0);
+ const AttributeDesc * attr_desc = tuple.getDesc(0);
+ const AttributeS attr1 = {attr_desc, *attr_data};
+ *syskey = *(attr1.Data.u_int32_value);
+ attr_data = tuple.getData(1);
+ attr_desc = tuple.getDesc(1);
+ const AttributeS attr2 = {attr_desc, *attr_data};
+ *nextid = *(attr2.Data.u_int64_value);
+ if (*syskey < 0x1000000)
+ {
+ return true;
+ }
+ return false;
+};
+
Uint16 Twiddle16(Uint16 in)
{
Uint16 retVal = 0;
=== modified file 'storage/ndb/tools/restore/Restore.hpp'
--- a/storage/ndb/tools/restore/Restore.hpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/tools/restore/Restore.hpp 2009-11-25 12:37:14 +0000
@@ -142,7 +142,9 @@ class TableS {
Uint32 m_auto_val_id;
Uint64 m_max_auto_val;
- bool isSysTable;
+ bool m_isSysTable;
+ bool m_isSYSTAB_0;
+
TableS *m_main_table;
Uint32 m_main_column_id;
Uint32 m_local_id;
@@ -238,6 +240,9 @@ public:
if(v > m_max_auto_val)
m_max_auto_val= v;
};
+
+ bool get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const;
+
/**
* Get attribute descriptor
*/
@@ -246,14 +251,19 @@ public:
}
bool getSysTable() const {
- return isSysTable;
+ return m_isSysTable;
}
const TableS *getMainTable() const {
return m_main_table;
}
- TableS& operator=(TableS& org) ;
+ TableS& operator=(TableS& org) ;
+
+ inline
+ const bool isSYSTAB_0() const {
+ return m_isSYSTAB_0;
+ }
}; // TableS;
class RestoreLogIterator;
@@ -436,6 +446,8 @@ NdbOut& operator<<(NdbOut& ndbout, const
NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);
+bool readSYSTAB_0(const TupleS & tup, Uint32 * syskey, Uint64 * nextid);
+
#endif
=== modified file 'storage/ndb/tools/restore/consumer_printer.cpp'
--- a/storage/ndb/tools/restore/consumer_printer.cpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/tools/restore/consumer_printer.cpp 2009-11-25 12:37:14 +0000
@@ -18,6 +18,7 @@
#include "consumer_printer.hpp"
extern FilteredNdbOut info;
+extern bool ga_dont_ignore_systab_0;
extern NdbRecordPrintFormat g_ndbrecord_print_format;
extern const char *tab_path;
@@ -44,6 +45,9 @@ BackupPrinter::tuple(const TupleS & tup,
info.setLevel(254);
info << tup.getTable()->getTableName() << "; ";
}
+ const TableS * table = tup.getTable();
+ if ((!ga_dont_ignore_systab_0) && table->isSYSTAB_0())
+ return;
m_ndbout << tup << g_ndbrecord_print_format.lines_terminated_by;
}
}
=== modified file 'storage/ndb/tools/restore/consumer_restore.cpp'
--- a/storage/ndb/tools/restore/consumer_restore.cpp 2009-06-22 08:23:35 +0000
+++ b/storage/ndb/tools/restore/consumer_restore.cpp 2009-11-25 12:37:14 +0000
@@ -135,8 +135,15 @@ BackupRestore::get_table(const NdbDictio
int cnt, id1, id2;
char db[256], schema[256];
- if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d",
- db, schema, &id1, &id2)) == 4){
+ if (strcmp(tab->getName(), "SYSTAB_0") == 0 ||
+ strcmp(tab->getName(), "sys/def/SYSTAB_0") == 0) {
+ /*
+ Restore SYSTAB_0 to itself
+ */
+ m_cache.m_new_table = tab;
+ }
+ else if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d",
+ db, schema, &id1, &id2)) == 4){
m_ndb->setDatabaseName(db);
m_ndb->setSchemaName(schema);
@@ -1162,6 +1169,8 @@ BackupRestore::endOfTables(){
void BackupRestore::tuple(const TupleS & tup, Uint32 fragmentId)
{
+ const TableS * tab = tup.getTable();
+
if (!m_restore)
return;
@@ -1178,12 +1187,19 @@ void BackupRestore::tuple(const TupleS &
if (cb == 0)
assert(false);
- m_free_callback = cb->next;
cb->retries = 0;
cb->fragId = fragmentId;
cb->tup = tup; // must do copy!
- tuple_a(cb);
+ if (tab->isSYSTAB_0())
+ {
+ tuple_SYSTAB_0(cb, *tab);
+ return;
+ }
+
+ m_free_callback = cb->next;
+
+ tuple_a(cb);
}
void BackupRestore::tuple_a(restore_callback_t *cb)
@@ -1339,6 +1355,59 @@ void BackupRestore::tuple_a(restore_call
exitHandler();
}
+void BackupRestore::tuple_SYSTAB_0(restore_callback_t *cb,
+ const TableS & tab)
+{
+ const TupleS & tup = cb->tup;
+ Uint32 syskey;
+ Uint64 nextid;
+
+ if (tab.get_auto_data(tup, &syskey, &nextid))
+ {
+ /*
+ We found a valid auto_increment value in SYSTAB_0
+ where syskey is a table_id and nextid is next auto_increment
+ value.
+ */
+ if (restoreAutoIncrement(cb, syskey, nextid) == -1)
+ exitHandler();
+ }
+}
+
+int BackupRestore::restoreAutoIncrement(restore_callback_t *cb,
+ Uint32 tableId, Uint64 value)
+{
+ /*
+ Restore the auto_increment value found in SYSTAB_0 from
+ backup. First map the old table id to the new table while
+ also checking that it is an actual table will some auto_increment
+ column. Note that the SYSTAB_0 table in the backup can contain
+ stale information from dropped tables.
+ */
+ int result = 0;
+ const NdbDictionary::Table* tab = (tableId < m_new_tables.size())? m_new_tables[tableId] : NULL;
+ if (tab && tab->getNoOfAutoIncrementColumns() > 0)
+ {
+ /*
+ Write the auto_increment value back into SYSTAB_0.
+ This is done in a separate transaction and could possibly
+ fail, so we retry if a temporary error is received.
+ */
+ while (cb->retries < 10)
+ {
+ if ((result = m_ndb->setAutoIncrementValue(tab, value, false) == -1))
+ {
+ if (errorHandler(cb))
+ {
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ return result;
+}
+
void BackupRestore::cback(int result, restore_callback_t *cb)
{
m_transactions--;
=== modified file 'storage/ndb/tools/restore/consumer_restore.hpp'
--- a/storage/ndb/tools/restore/consumer_restore.hpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/tools/restore/consumer_restore.hpp 2009-11-25 12:37:14 +0000
@@ -75,6 +75,9 @@ public:
virtual void tuple(const TupleS &, Uint32 fragId);
virtual void tuple_free();
virtual void tuple_a(restore_callback_t *cb);
+ virtual void tuple_SYSTAB_0(restore_callback_t *cb, const TableS &);
+ virtual int restoreAutoIncrement(restore_callback_t *cb,
+ Uint32 tableId, Uint64 value);
virtual void cback(int result, restore_callback_t *cb);
virtual bool errorHandler(restore_callback_t *cb);
virtual void exitHandler();
=== modified file 'storage/ndb/tools/restore/restore_main.cpp'
--- a/storage/ndb/tools/restore/restore_main.cpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/tools/restore/restore_main.cpp 2009-11-25 12:37:14 +0000
@@ -36,7 +36,7 @@ extern FilteredNdbOut debug;
static int ga_nodeId = 0;
static int ga_nParallelism = 128;
static int ga_backupId = 0;
-static bool ga_dont_ignore_systab_0 = false;
+bool ga_dont_ignore_systab_0 = false;
static bool ga_no_upgrade = false;
static Vector<class BackupConsumer *> g_consumers;
static BackupPrinter* g_printer = NULL;
@@ -162,7 +162,7 @@ static struct my_option my_long_options[
(uchar**) &ga_backupPath, (uchar**) &ga_backupPath, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "dont_ignore_systab_0", 'f',
- "Experimental. Do not ignore system table during restore.",
+ "Do not ignore system table during --print-data.",
(uchar**) &ga_dont_ignore_systab_0, (uchar**) &ga_dont_ignore_systab_0, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "ndb-nodegroup-map", OPT_NDB_NODEGROUP_MAP,
@@ -564,7 +564,7 @@ clearConsumers()
static inline bool
checkSysTable(const TableS* table)
{
- return ga_dont_ignore_systab_0 || ! table->getSysTable();
+ return ! table->getSysTable();
}
static inline bool
@@ -588,6 +588,12 @@ isIndex(const TableS* table)
}
static inline bool
+isSYSTAB_0(const TableS* table)
+{
+ return table->isSYSTAB_0();
+}
+
+static inline bool
checkDbAndTableName(const TableS* table)
{
if (g_tables.size() == 0 &&
@@ -824,6 +830,10 @@ main(int argc, char** argv)
table_output.push_back(NULL);
if (!checkDbAndTableName(table))
continue;
+ if (isSYSTAB_0(table))
+ {
+ table_output[i]= ndbout.m_out;
+ }
if (checkSysTable(table))
{
if (!tab_path || isBlobTable(table) || isIndex(table))
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-6.2 branch (Martin.Skold:3038) Bug#48005 | Martin Skold | 25 Nov |