diff --git a/mysql-test/r/ndb_bug26793.result b/mysql-test/r/ndb_bug26793.result new file mode 100644 index 00000000000..a9a8a798546 --- /dev/null +++ b/mysql-test/r/ndb_bug26793.result @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE `test` ( +`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , +`t` VARCHAR( 10 ) NOT NULL +) ENGINE = ndbcluster; +GRANT USAGE ON *.* TO user1@localhost IDENTIFIED BY 'pass'; +DROP TABLE `test`.`test`; +drop user user1@localhost; diff --git a/mysql-test/r/rpl_colSize.result b/mysql-test/r/rpl_colSize.result new file mode 100644 index 00000000000..91456742833 --- /dev/null +++ b/mysql-test/r/rpl_colSize.result @@ -0,0 +1,179 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP TABLE IF EXISTS t1; +**** Testing WL#3228 changes. **** +*** Create "wider" table on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 ( +a float (47), +b double (143,9), +c decimal (65,30), +d numeric (4,0), +e bit (32), +f char (21), +g varchar (1300), +h binary (33), +j varbinary (200), +k enum ('5','6','7', '8','9','0'), +l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'), +m TINYBLOB, +n BLOB, +o MEDIUMBLOB, +p LONGBLOB, +q TINYTEXT, +r TEXT, +s MEDIUMTEXT, +t LONGTEXT +); +*** Create same table on master but with narrow columns *** +CREATE TABLE t1 ( +a float (44), +b double (10,3), +c decimal (10,2), +d numeric (3,0), +e bit (16), +f char (10), +g varchar (100), +h binary (20), +j varbinary (20), +k enum ('5','6','7'), +l set ('1','2','3','4','5','6','7','8','9','0'), +m TINYBLOB, +n BLOB, +o MEDIUMBLOB, +p LONGBLOB, +q TINYTEXT, +r TEXT, +s MEDIUMTEXT, +t LONGTEXT +); +RESET MASTER; +*** Start replication *** +START SLAVE; +*** Insert data on master and display it. *** +INSERT INTO t1 () VALUES ( +17.567, +2.123, +10.20, +125, +hex(64), +'TEST', +'This is a test', +'binary data', +'more binary data', +'6', +'7', +"blob 1", +"blob 2", +"blob 3", +"blob 4", +"text 1", +"text 2", +"text 3", +"text 4"); +SELECT * FROM t1 ORDER BY a; +a b c d e f g h j k l m n o p q r s t +17.567 2.123 10.20 125 # TEST This is a test # more binary data 6 7 blob 1 blob 2 blob 3 blob 4 text 1 text 2 text 3 text 4 +*** Select data from slave to compare *** +SELECT * FROM t1 ORDER BY a; +a b c d e f g h j k l m n o p q r s t +17.567 2.123000000 10.200000000000000000000000000000 125 # TEST This is a test # more binary data 6 7 blob 1 blob 2 blob 3 blob 4 text 1 text 2 text 3 text 4 +DROP TABLE t1; +Create varchar table on master +CREATE TABLE t1 ( +a VARCHAR(50), +b VARCHAR(100), +c VARCHAR(300), +d CHAR(5) +); +Alter varchar table on slave +ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100); +ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400); +ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500); +ALTER TABLE t1 CHANGE COLUMN d d CHAR(100); +Insert some values and select them on master +INSERT INTO t1 VALUES ("This is a test of col a.", +"This is another test of col b.", +"This is a test of the large col c.", +"Col d"); +SELECT * FROM t1; +a b c d +This is a test of col a. This is another test of col b. This is a test of the large col c. Col d +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(50) DEFAULT NULL, + `b` varchar(100) DEFAULT NULL, + `c` varchar(300) DEFAULT NULL, + `d` char(5) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Insert some values and select them on slave +SELECT * FROM t1; +a b c d +This is a test of col a. This is another test of col b. This is a test of the large col c. Col d +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(100) DEFAULT NULL, + `b` varchar(400) DEFAULT NULL, + `c` varchar(500) DEFAULT NULL, + `d` char(100) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +Create bit table on master +CREATE TABLE t1 ( +a BIT(7), +b BIT(8), +c BIT(21), +d BIT(11), +e BIT(11) +); +Create bit table on slave +DROP TABLE t1; +CREATE TABLE t1 ( +a BIT(16), +b BIT(22), +c BIT(54), +d BIT(25), +e BIT(13) +); +Insert some values and select them on master +INSERT INTO t1 VALUES ( +b'1010101', +b'10101011', +b'101010110101010101111', +b'10101010101', +b'10101011111' + ); +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +BIN(a) BIN(b) BIN(c) BIN(d) BIN(e) +1010101 10101011 101010110101010101111 10101010101 10101011111 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bit(7) DEFAULT NULL, + `b` bit(8) DEFAULT NULL, + `c` bit(21) DEFAULT NULL, + `d` bit(11) DEFAULT NULL, + `e` bit(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Insert some values and select them on master +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +BIN(a) BIN(b) BIN(c) BIN(d) BIN(e) +1010101 10101011 101010110101010101111 10101010101 10101011111 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bit(16) DEFAULT NULL, + `b` bit(22) DEFAULT NULL, + `c` bit(54) DEFAULT NULL, + `d` bit(25) DEFAULT NULL, + `e` bit(13) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +*** Cleanup *** +DROP TABLE t1; diff --git a/mysql-test/r/rpl_extraColmaster_innodb.result b/mysql-test/r/rpl_extraColmaster_innodb.result new file mode 100644 index 00000000000..27d6592a7ad Binary files /dev/null and b/mysql-test/r/rpl_extraColmaster_innodb.result differ diff --git a/mysql-test/r/rpl_extraColmaster_myisam.result b/mysql-test/r/rpl_extraColmaster_myisam.result new file mode 100644 index 00000000000..9a77ae6ca19 Binary files /dev/null and b/mysql-test/r/rpl_extraColmaster_myisam.result differ diff --git a/mysql-test/r/rpl_row_extraColmaster_ndb.result b/mysql-test/r/rpl_row_extraColmaster_ndb.result new file mode 100644 index 00000000000..230b880e46f Binary files /dev/null and b/mysql-test/r/rpl_row_extraColmaster_ndb.result differ diff --git a/mysql-test/r/rpl_stm_extraColmaster_ndb.result b/mysql-test/r/rpl_stm_extraColmaster_ndb.result new file mode 100644 index 00000000000..30332e9e7c8 Binary files /dev/null and b/mysql-test/r/rpl_stm_extraColmaster_ndb.result differ diff --git a/mysql-test/suite/ndb/r/ndb_read_multi_range.result b/mysql-test/suite/ndb/r/ndb_read_multi_range.result index 8443d0473a8..4c3496f3f47 100644 --- a/mysql-test/suite/ndb/r/ndb_read_multi_range.result +++ b/mysql-test/suite/ndb/r/ndb_read_multi_range.result @@ -473,3 +473,22 @@ a b 1 1 10 10 drop table t1, t2; +create table t1 (id int primary key) engine ndb; +insert into t1 values (1), (2), (3); +create table t2 (id int primary key) engine ndb; +insert into t2 select id from t1; +create trigger kaboom after delete on t1 +for each row begin +delete from t2 where id=old.id; +end| +select * from t1 order by id; +id +1 +2 +3 +delete from t1 where id in (1,2); +select * from t2 order by id; +id +3 +drop trigger kaboom; +drop table t1; diff --git a/mysql-test/suite/ndb/t/ndb_read_multi_range.test b/mysql-test/suite/ndb/t/ndb_read_multi_range.test index ecca1f9862c..1965874940b 100644 --- a/mysql-test/suite/ndb/t/ndb_read_multi_range.test +++ b/mysql-test/suite/ndb/t/ndb_read_multi_range.test @@ -315,5 +315,26 @@ partition by key(a); insert into t2 values (1,1), (10,10); select * from t2 where a in (1,10) order by a; - drop table t1, t2; + +#bug#30337 + +create table t1 (id int primary key) engine ndb; +insert into t1 values (1), (2), (3); + +create table t2 (id int primary key) engine ndb; +insert into t2 select id from t1; + +delimiter |; +create trigger kaboom after delete on t1 +for each row begin + delete from t2 where id=old.id; +end| +delimiter ;| + +select * from t1 order by id; +delete from t1 where id in (1,2); +select * from t2 order by id; + +drop trigger kaboom; +drop table t1; diff --git a/mysql-test/t/ndb_bug26793.test b/mysql-test/t/ndb_bug26793.test new file mode 100644 index 00000000000..f35d8808c1a --- /dev/null +++ b/mysql-test/t/ndb_bug26793.test @@ -0,0 +1,35 @@ +-- source include/have_ndb.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE `test` ( +`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , +`t` VARCHAR( 10 ) NOT NULL +) ENGINE = ndbcluster; + +# Add user1@localhost with a specific password +# and connect as that user +GRANT USAGE ON *.* TO user1@localhost IDENTIFIED BY 'pass'; +connect (user1,localhost,user1,pass,*NO-ONE*); + +# Run the query 100 times +disable_query_log; +disable_result_log; +let $i= 100; +while ($i) +{ +select count(*) from information_schema.tables union all select count(*) from information_schema.tables union all select count(*) from information_schema.tables; +dec $i; +} +enable_query_log; +enable_result_log; + +disconnect user1; + +# Switch back to the default connection and cleanup +connection default; +DROP TABLE `test`.`test`; +drop user user1@localhost; + diff --git a/mysql-test/t/rpl_colSize.test b/mysql-test/t/rpl_colSize.test new file mode 100644 index 00000000000..44fb878d4d2 --- /dev/null +++ b/mysql-test/t/rpl_colSize.test @@ -0,0 +1,216 @@ +################################################################## +# rpl_colSize # +# # +# This test is designed to test the changes included in WL#3228. # +# The changes include the ability to replicate with the master # +# having columns that are smaller (shorter) than the slave. # +################################################################## + +-- source include/master-slave.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo **** Testing WL#3228 changes. **** +--echo *** Create "wider" table on slave *** +sync_slave_with_master; +STOP SLAVE; +RESET SLAVE; + +eval CREATE TABLE t1 ( + a float (47), + b double (143,9), + c decimal (65,30), + d numeric (4,0), + e bit (32), + f char (21), + g varchar (1300), + h binary (33), + j varbinary (200), + k enum ('5','6','7', '8','9','0'), + l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +--echo *** Create same table on master but with narrow columns *** +connection master; +eval CREATE TABLE t1 ( + a float (44), + b double (10,3), + c decimal (10,2), + d numeric (3,0), + e bit (16), + f char (10), + g varchar (100), + h binary (20), + j varbinary (20), + k enum ('5','6','7'), + l set ('1','2','3','4','5','6','7','8','9','0'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +RESET MASTER; + +--echo *** Start replication *** +connection slave; +START SLAVE; + +--echo *** Insert data on master and display it. *** +connection master; + +INSERT INTO t1 () VALUES ( + 17.567, + 2.123, + 10.20, + 125, + hex(64), + 'TEST', + 'This is a test', + 'binary data', + 'more binary data', + '6', + '7', + "blob 1", + "blob 2", + "blob 3", + "blob 4", + "text 1", + "text 2", + "text 3", + "text 4"); + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +--echo *** Select data from slave to compare *** +sync_slave_with_master; +connection slave; + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +# Test boundary limits of varchar and char fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col a +# >255/<256 with m < s, m > s, and m == s <-- error will be caught in BUG#22086 +# <256/>255 with m < s, m > s, and m == s <-- col b +# >255/>255 with m < s, m > s, and m == s <-- col c +# +# Test boundary limits of CHAR fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col d +# >255/<256 with m < s, m > s, and m == s <-- error char limited to 255 chars +# <256/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars +# >255/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars + +connection master; +DROP TABLE t1; + +--echo Create varchar table on master +CREATE TABLE t1 ( + a VARCHAR(50), + b VARCHAR(100), + c VARCHAR(300), + d CHAR(5) +); + +sync_slave_with_master slave; + +--echo Alter varchar table on slave +ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100); +ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400); +ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500); +ALTER TABLE t1 CHANGE COLUMN d d CHAR(100); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ("This is a test of col a.", + "This is another test of col b.", + "This is a test of the large col c.", + "Col d"); +SELECT * FROM t1; +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on slave +SELECT * FROM t1; +SHOW CREATE TABLE t1; + + +# Test boundary limits of bit fields +# m < s, m % 8 != 0, and s % 8 == 0 col a +# m < s, m % 8 == 0, and s % 8 != 0 col b +# m < s, m % 8 != 0, and s % 8 != 0 col c +# m > s, m % 8 != 0, and s % 8 == 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 == 0, and s % 8 != 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 != 0, and s % 8 != 0 <-- error will be caught in BUG#22086 + +connection master; +DROP TABLE t1; + +--echo Create bit table on master +CREATE TABLE t1 ( + a BIT(7), + b BIT(8), + c BIT(21), + d BIT(11), + e BIT(11) +); + +sync_slave_with_master slave; + +--echo Create bit table on slave +DROP TABLE t1; +CREATE TABLE t1 ( + a BIT(16), + b BIT(22), + c BIT(54), + d BIT(25), + e BIT(13) +); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ( + b'1010101', + b'10101011', + b'101010110101010101111', + b'10101010101', + b'10101011111' + ); + +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on master +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +SHOW CREATE TABLE t1; + +--echo *** Cleanup *** +connection master; +DROP TABLE t1; +sync_slave_with_master; + +# END 5.1 Test Case diff --git a/mysql-test/t/rpl_extraColmaster_innodb-master.opt b/mysql-test/t/rpl_extraColmaster_innodb-master.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_extraColmaster_innodb-master.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_extraColmaster_innodb-slave.opt b/mysql-test/t/rpl_extraColmaster_innodb-slave.opt new file mode 100644 index 00000000000..1338b6eba04 --- /dev/null +++ b/mysql-test/t/rpl_extraColmaster_innodb-slave.opt @@ -0,0 +1 @@ + --innodb diff --git a/mysql-test/t/rpl_extraColmaster_innodb.test b/mysql-test/t/rpl_extraColmaster_innodb.test new file mode 100644 index 00000000000..082c22329fa --- /dev/null +++ b/mysql-test/t/rpl_extraColmaster_innodb.test @@ -0,0 +1,15 @@ +############################################################# +# Purpose: To test having extra columns on the master WL#3915 +############################################################# +-- source include/master-slave.inc +-- source include/have_innodb.inc + +let $engine_type = 'InnoDB'; + +set binlog_format=row; +-- source extra/rpl_tests/rpl_extraMaster_Col.test + +set binlog_format=statement; +-- source extra/rpl_tests/rpl_extraMaster_Col.test + + diff --git a/mysql-test/t/rpl_extraColmaster_myisam.test b/mysql-test/t/rpl_extraColmaster_myisam.test new file mode 100644 index 00000000000..5bbd7953294 --- /dev/null +++ b/mysql-test/t/rpl_extraColmaster_myisam.test @@ -0,0 +1,13 @@ +############################################################# +# Purpose: To test having extra columns on the master WL#3915 +############################################################# +-- source include/master-slave.inc + +let $engine_type = 'MyISAM'; + +set binlog_format=row; +-- source extra/rpl_tests/rpl_extraMaster_Col.test + +set binlog_format=statement; +-- source extra/rpl_tests/rpl_extraMaster_Col.test + diff --git a/mysql-test/t/rpl_row_extraColmaster_ndb.test b/mysql-test/t/rpl_row_extraColmaster_ndb.test new file mode 100644 index 00000000000..b91947e52e2 --- /dev/null +++ b/mysql-test/t/rpl_row_extraColmaster_ndb.test @@ -0,0 +1,12 @@ +########################################### +# Purpose: Wrapper for rpl_extraMaster_Col.test +# Using NDB +########################################### +-- source include/have_ndb.inc +-- source include/ndb_master-slave.inc +-- source include/have_binlog_format_row.inc + +let $engine_type = 'NDB'; + +-- source extra/rpl_tests/rpl_extraMaster_Col.test + diff --git a/mysql-test/t/rpl_stm_extraColmaster_ndb.test b/mysql-test/t/rpl_stm_extraColmaster_ndb.test new file mode 100644 index 00000000000..84734204439 --- /dev/null +++ b/mysql-test/t/rpl_stm_extraColmaster_ndb.test @@ -0,0 +1,13 @@ +########################################### +# Purpose: Wrapper for rpl_extraMaster_Col.test +# Using NDB +########################################### +-- source include/have_ndb.inc +-- source include/ndb_master-slave.inc +-- source include/have_binlog_format_statement.inc + +let $engine_type = 'NDB'; + +-- source extra/rpl_tests/rpl_extraMaster_Col.test + + diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 3b68b3828d2..f6c41af5312 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2817,6 +2817,8 @@ int ha_ndbcluster::write_row(uchar *record) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); + else if (!(thd->options & OPTION_BIN_LOG)) + op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); } m_rows_changed++; @@ -3107,6 +3109,8 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); + else if (!(thd->options & OPTION_BIN_LOG)) + op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); } /* Execute update operation if we are not doing a scan for update @@ -3177,6 +3181,9 @@ int ha_ndbcluster::delete_row(const uchar *record) else if (thd->slave_thread) ((NdbOperation *)trans->getLastDefinedOperation())-> setAnyValue(thd->server_id); + else if (!(thd->options & OPTION_BIN_LOG)) + ((NdbOperation *)trans->getLastDefinedOperation())-> + setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); } if (!(m_primary_key_update || m_delete_cannot_batch)) // If deleting from cursor, NoCommit will be handled in next_result @@ -3215,6 +3222,8 @@ int ha_ndbcluster::delete_row(const uchar *record) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); + else if (!(thd->options & OPTION_BIN_LOG)) + op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); } } @@ -3960,6 +3969,8 @@ int ha_ndbcluster::info(uint flag) DBUG_PRINT("info", ("HA_STATUS_AUTO")); if (m_table && table->found_next_number_field) { + if ((my_errno= check_ndb_connection())) + DBUG_RETURN(my_errno); Ndb *ndb= get_ndb(); Ndb_tuple_id_range_guard g(m_share); @@ -8536,7 +8547,8 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, if (uses_blob_value() || (cur_index_type == UNIQUE_INDEX && has_null_in_unique_index(active_index) && - null_value_index_search(ranges, ranges+range_count, buffer))) + null_value_index_search(ranges, ranges+range_count, buffer)) + || m_delete_cannot_batch || m_update_cannot_batch) { m_disable_multi_read= TRUE; DBUG_RETURN(handler::read_multi_range_first(found_range_p, diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index c91faac388f..468adba0aa0 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -114,6 +114,9 @@ NDB_SHARE *ndb_apply_status_share= 0; NDB_SHARE *ndb_schema_share= 0; pthread_mutex_t ndb_schema_share_mutex; +extern my_bool opt_log_slave_updates; +static my_bool g_ndb_log_slave_updates; + /* Schema object distribution handling */ HASH ndb_schema_objects; typedef struct st_ndb_schema_object { @@ -3296,6 +3299,14 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp, originating_server_id); return 0; } + else if (!g_ndb_log_slave_updates) + { + /* + This event comes from a slave applier since it has an originating + server id set. Since option to log slave updates is not set, skip it. + */ + return 0; + } TABLE *table= share->table; DBUG_ASSERT(trans.good()); @@ -3942,6 +3953,8 @@ restart: ! IS_NDB_BLOB_PREFIX(pOp->getEvent()->getTable()->getName())); DBUG_ASSERT(gci <= ndb_latest_received_binlog_epoch); + /* initialize some variables for this epoch */ + g_ndb_log_slave_updates= opt_log_slave_updates; i_ndb-> setReportThreshEventGCISlip(ndb_report_thresh_binlog_epoch_slip); i_ndb->setReportThreshEventFreeMem(ndb_report_thresh_binlog_mem_usage); diff --git a/storage/ndb/ndbapi-examples/ndbapi_async1/ndbapi_async1.cpp b/storage/ndb/ndbapi-examples/ndbapi_async1/ndbapi_async1.cpp index a195a419aaf..1f19f36d674 100644 --- a/storage/ndb/ndbapi-examples/ndbapi_async1/ndbapi_async1.cpp +++ b/storage/ndb/ndbapi-examples/ndbapi_async1/ndbapi_async1.cpp @@ -75,7 +75,7 @@ int main(int argc, char** argv) exit(-1); } - if (cluster_connection->wait_until_ready(30,0)) + if (cluster_connection->wait_until_ready(30,0) < 0) { std::cout << "Cluster was not ready within 30 secs." << std::endl; exit(-1); diff --git a/storage/ndb/tools/ndb_size.pl b/storage/ndb/tools/ndb_size.pl index 4ecdc297cd3..3537a9e8490 100644 --- a/storage/ndb/tools/ndb_size.pl +++ b/storage/ndb/tools/ndb_size.pl @@ -169,7 +169,9 @@ use Class::MethodMaker [ vdm_versions ddm_versions ) ], scalar => [ qw( name - rows ) ], + rows + schema + real_table_name) ], hash => [ qw( columns indexes indexed_columns @@ -198,6 +200,16 @@ use Class::MethodMaker [ scalar => [ { -default=> 4 },'align'], ]; +sub table_name +{ + my ($self) = @_; + if ($self->real_table_name) { + return $self->real_table_name; + }else { + return $self->name; + } +} + sub compute_row_size { my ($self, $releases) = @_; @@ -391,14 +403,30 @@ sub compute_estimate package main; -my ($dbh,$database,$hostname,$user,$password,$help,$savequeries,$loadqueries,$debug,$format); +my ($dbh, + $database, + $socket, + $hostname, + $user, + $password); + +my ($help, + $savequeries, + $loadqueries, + $debug, + $format, + $excludetables, + $excludedbs); GetOptions('database|d=s'=>\$database, 'hostname=s'=>\$hostname, + 'socket=s'=>\$socket, 'user|u=s'=>\$user, 'password|p=s'=>\$password, 'savequeries|s=s'=>\$savequeries, 'loadqueries|l=s'=>\$loadqueries, + 'excludetables=s'=>\$excludetables, + 'excludedbs=s'=>\$excludedbs, 'help|usage|h!'=>\$help, 'debug'=>\$debug, 'format|f=s'=>\$format, @@ -406,32 +434,75 @@ GetOptions('database|d=s'=>\$database, my $report= new MySQL::NDB::Size::Report; -if($help || !$database) +if($help) { print STDERR "Usage:\n"; - print STDERR "\tndb_size.pl --database= [--hostname=]" + print STDERR "\tndb_size.pl --database=|ALL [--hostname=] " + ."[--socket=] " ."[--user=] [--password=] [--help|-h] [--format=(html|text)] [--loadqueries=] [--savequeries=]\n\n"; + print STDERR "\t--database= ALL may be specified to examine all " + ."databases\n"; print STDERR "\t--hostname=: can be used to designate a " ."specific port\n"; print STDERR "\t--hostname defaults to localhost\n"; print STDERR "\t--user and --password default to empty string\n"; print STDERR "\t--format=(html|text) Output format\n"; + print STDERR "\t--excludetables Comma separated list of table names to skip\n"; + print STDERR "\t--excludedbs Comma separated list of database names to skip\n"; print STDERR "\t--savequeries= saves all queries to the DB into \n"; print STDERR "\t--loadqueries= loads query results from . Doesn't connect to DB.\n"; exit(1); } + $hostname= 'localhost' unless $hostname; my %queries; # used for loadqueries/savequeries if(!$loadqueries) { - my $dsn = "DBI:mysql:database=$database;host=$hostname"; + my $dsn = "DBI:mysql:host=$hostname"; + $dsn.= ";mysql_socket=$socket" if ($socket); $dbh= DBI->connect($dsn, $user, $password) or exit(1); - $report->database($database); $report->dsn($dsn); } + +my @dbs; +if ($database && !($database =~ /^ALL$/i)) +{ + @dbs = split(',', $database); +} +else +{ + # Do all databases + @dbs = map { $_->[0] } @{ $dbh->selectall_arrayref("show databases") }; +} + +my %withdb = map {$_ => 1} @dbs; +foreach (split ",", $excludedbs || '') +{ + delete $withdb{$_}; +} +delete $withdb{'mysql'}; +delete $withdb{'INFORMATION_SCHEMA'}; +delete $withdb{'information_schema'}; + +my $dblist = join (',', map { $dbh->quote($_) } keys %withdb ); + +$excludetables = join (',', map { $dbh->quote($_) } split ',', $excludetables ) + if $excludetables; + +if(!$loadqueries) +{ + if (scalar(keys %withdb)>1) + { + $report->database("databases: $dblist"); + } + else + { + $report->database("database: $dblist"); + } +} else { open Q,"< $loadqueries"; @@ -441,7 +512,6 @@ else %queries= %$e; close Q; $report->database("file:$loadqueries"); - $report->dsn("file:$loadqueries"); } $report->versions('4.1','5.0','5.1'); @@ -454,7 +524,25 @@ if($loadqueries) } else { - $tables= $dbh->selectall_arrayref("show tables"); + my $sql= "select t.TABLE_NAME,t.TABLE_SCHEMA " . + " from information_schema.TABLES t " . + " where t.TABLE_SCHEMA in ( $dblist ) "; + + $sql.=" and t.TABLE_NAME not in " . + " ( $excludetables )" + if ($excludetables); + + $tables= $dbh->selectall_arrayref($sql); + + if (!$tables) { + print "WARNING: problem selecing from INFORMATION SCHEMA ($sql)\n"; + if ($#dbs>0) { + print "\t attempting to fallback to show tables from $database"; + $tables= $dbh->selectall_arrayref("show tables from $database\n"); + } else { + print "All Databases not supported in 4.1. Please specify --database=\n"; + } + } $queries{"show tables"}= $tables; } @@ -510,6 +598,8 @@ sub do_table { {$col->dm(4)} elsif($type =~ /float/) { + my @sz= split ',', $size; + $size= $sz[0]+$sz[1]; if(!defined($size) || $size<=24) {$col->dm(4)} else @@ -543,9 +633,10 @@ sub do_table { $col->dm($fixed); if(!$col->Key()) # currently keys must be non varsized { - my $sql= "select avg(length(`" - .$colname - ."`)) from `".$t->name().'`'; + my $sql= sprintf("select avg(length(`%s`)) " . + " from `%s`.`%s` " , + $colname, $t->schema(), $t->table_name()); + my @dynamic; if($loadqueries) { @@ -573,9 +664,11 @@ sub do_table { $blobhunk= 8000 if $type=~ /longblob/; $blobhunk= 4000 if $type=~ /mediumblob/; - my $sql= "select SUM(CEILING(". - "length(`$colname`)/$blobhunk))" - ."from `".$t->name."`"; + my $sql= sprintf("select SUM(CEILING(length(`%s`)/%s)) " . + " from `%s`.`%s`" , + $colname, $blobhunk, + $t->schema(), $t->table_name() ); + my @blobsize; if($loadqueries) { @@ -589,11 +682,12 @@ sub do_table { $blobsize[0]=0 if !defined($blobsize[0]); # Is a supporting table, add it to the lists: - $report->supporting_tables_set($t->name()."\$BLOB_$colname" => 1); - $t->supporting_tables_push($t->name()."\$BLOB_$colname"); + $report->supporting_tables_set($t->schema().".".$t->name()."\$BLOB_$colname" => 1); + $t->supporting_tables_push($t->schema().".".$t->name()."\$BLOB_$colname"); my $st= new MySQL::NDB::Size::Table(name => $t->name()."\$BLOB_$colname", + schema => $t->schema(), rows => $blobsize[0], row_dm_overhead => { '4.1' => 12, @@ -632,7 +726,9 @@ sub do_table { $col->size($size); $t->columns_set( $colname => $col ); } - $report->tables_set( $t->name => $t ); + #print "setting tables: ",$t->schema(), $t->table_name(), $t->name, $t->real_table_name || "" , "\n"; + # Use $t->name here instead of $t->table_name() to avoid namespace conflicts + $report->tables_set( $t->schema().".".$t->name() => $t ); # And now... the IndexMemory usage. # @@ -727,14 +823,16 @@ sub do_table { # Is a supporting table, add it to the lists: my $idxname= $t->name().'_'.join('_',@{$indexes{$index}{columns}}). "\$unique"; - $report->supporting_tables_set($idxname => 1); - $t->supporting_tables_push($idxname); + $report->supporting_tables_set($t->schema().".".$idxname => 1); + $t->supporting_tables_push($t->schema().".".$idxname); $t->indexed_columns_set($_ => 1) foreach @{$indexes{$index}{columns}}; my $st= new MySQL::NDB::Size::Table(name => $idxname, + real_table_name => $t->table_name(), rows => $count[0], + schema => $t->schema(), row_dm_overhead => { '4.1' => 12, '5.0' => 12, @@ -745,7 +843,6 @@ sub do_table { row_ddm_overhead => { '5.1' => 8 }, ); - do_table($st, \%idxcols, { @@ -766,9 +863,10 @@ sub do_table { foreach(@{$tables}) { my $table= @{$_}[0]; + my $schema = @{$_}[1] || $database; my $info; { - my $sql= 'describe `'.$table.'`'; + my $sql= 'describe `'.$schema.'`.`'.$table.'`'; if($loadqueries) { $info= $queries{$sql}; @@ -781,7 +879,7 @@ foreach(@{$tables}) } my @count; { - my $sql= 'select count(*) from `'.$table.'`'; + my $sql= 'select count(*) from `'.$schema.'`.`'.$table.'`'; if($loadqueries) { @count= @{$queries{$sql}}; @@ -797,7 +895,7 @@ foreach(@{$tables}) { my @show_indexes; { - my $sql= "show index from `".$table.'`'; + my $sql= "show index from `".$schema.'`.`'.$table.'`'; if($loadqueries) { @show_indexes= @{$queries{$sql}}; @@ -826,6 +924,7 @@ foreach(@{$tables}) } } my $t= new MySQL::NDB::Size::Table(name => $table, + schema => $schema, rows => $count[0], row_dm_overhead => { '4.1' => 12, @@ -974,6 +1073,8 @@ if($debug) eval 'print STDERR Dumper($report)'; } +$format= "text" unless $format; + if($format eq 'text') { my $text_out= new MySQL::NDB::Size::Output::Text($report); @@ -984,12 +1085,6 @@ elsif($format eq 'html') my $html_out= new MySQL::NDB::Size::Output::HTML($report); $html_out->output(); } -else -{ - # default to text output - my $text_out= new MySQL::NDB::Size::Output::Text($report); - $text_out->output(); -} package MySQL::NDB::Size::Output::Text; use Data::Dumper; @@ -1008,7 +1103,7 @@ sub output my $self= shift; my $r= $self->{report}; - print $self->ul("ndb_size.pl report for database ". $r->database(). + print $self->ul("ndb_size.pl report for ". $r->database(). " (".(($r->tables_count()||0)-($r->supporting_tables_count()||0)). " tables)"); @@ -1188,8 +1283,8 @@ sub output my $st= $r->tables->{$_}; foreach(@{$st->indexes_keys()}) { - printf $f, $st->name() if $_ eq 'PRIMARY'; - printf $f, $st->name().$_ if $_ ne 'PRIMARY'; + printf $f, $st->schema().".".$st->name() if $_ eq 'PRIMARY'; + printf $f, $st->schema().".".$st->name().$_ if $_ ne 'PRIMARY'; my $sti= $st->indexes->{$_}; printf $v, ($sti->ver_im_exists($_)) ?$sti->ver_im->{$_} @@ -1367,7 +1462,7 @@ print < ENDHTML - print $self->h1("ndb_size.pl report for database ". $r->database(). + print $self->h1("ndb_size.pl report for ". $r->database(). " (".(($r->tables_count()||0)-($r->supporting_tables_count()||0)). " tables)"); @@ -1579,8 +1674,8 @@ ENDHTML foreach(@{$st->indexes_keys()}) { my @r; - push @r, $st->name() if $_ eq 'PRIMARY'; - push @r, $st->name().$_ if $_ ne 'PRIMARY'; + push @r, $st->schema().".".$st->name() if $_ eq 'PRIMARY'; + push @r, $st->schema().".".$st->name().$_ if $_ ne 'PRIMARY'; my $sti= $st->indexes->{$_}; push @r, ($sti->ver_im_exists($_)) ?$sti->ver_im->{$_}