diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 629618609a3..24f921a4877 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -19,11 +19,24 @@ EXTRA_DIST = mysql.info INSTALL-BINARY @extra_docs@ # automake only seems to take care of this automatically, # if we're building the info page from texi directly. install-data-hook: $(srcdir)/mysql.info - $(mkinstalldirs) $(DESTDIR)$(infodir) - $(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir) + if test `basename $(prefix)` = "mysql" ; then \ + $(mkinstalldirs) $(DESTDIR)$(prefix)/docs ; \ + $(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(prefix)/docs ; \ + test ! -f $(top_srcdir)/ChangeLog || $(INSTALL_DATA) $(top_srcdir)/ChangeLog $(DESTDIR)$(prefix)/docs ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(infodir) $(DESTDIR)$(pkgdatadir) ; \ + $(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir) ; \ + test ! -f $(top_srcdir)/ChangeLog || $(INSTALL_DATA) $(top_srcdir)/ChangeLog $(DESTDIR)$(pkgdatadir) ; \ + fi uninstall-local: - @RM@ -f $(DESTDIR)$(infodir)/mysql.info + if test `basename $(prefix)` = "mysql" ; then \ + @RM@ -f $(DESTDIR)$(prefix)/docs/mysql.info ; \ + @RM@ -f $(DESTDIR)$(prefix)/docs/ChangeLog ; \ + else \ + @RM@ -f $(DESTDIR)$(infodir)/mysql.info ; \ + @RM@ -f $(DESTDIR)$(pkgdatadir)/ChangeLog ; \ + fi # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Makefile.am b/Makefile.am index f999df86acf..60b4f9bd07c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,20 +132,33 @@ test-bt: -cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --comment=ps --force --timer \ --skip-ndbcluster --ps-protocol - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --comment=normal+rowrepl --force --timer \ - --skip-ndbcluster --mysqld=--binlog-format=row -if [ -e bin/ndbd -o -e storage/ndb/src/kernel/ndbd ] ; then \ cd mysql-test ; \ MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --comment=ps+rowrepl+NDB --force --timer \ - --ps-protocol --mysqld=--binlog-format=row ; \ + @PERL@ ./mysql-test-run.pl --comment=ndb+rpl_ndb+ps --force --timer \ + --ps-protocol --mysqld=--binlog-format=row --suite=ndb,rpl_ndb ; \ MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --comment=NDB --force --timer \ + @PERL@ ./mysql-test-run.pl --comment=ndb --force --timer \ --with-ndbcluster-only ; \ else \ echo "no program found for 'ndbcluster' tests - skipped testing" ; \ fi + -cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --force --comment=funcs1+ps --ps-protocol --suite=funcs_1 + -cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --force --comment=funcs2 --suite=funcs_2 + -cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --force --comment=partitions --suite=parts + -cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress + -if [ -d mysql-test/suite/nist ] ; then \ + cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --comment=nist --force --suite=nist ; \ + fi + -if [ -d mysql-test/suite/nist ] ; then \ + cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --comment=nist+ps --force --suite=nist --ps-protocol ; \ + fi -if [ -e bin/mysqltest_embedded -o -e libmysqld/examples/mysqltest_embedded ] ; then \ cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --comment=embedded --force --timer \ @@ -153,24 +166,6 @@ test-bt: else \ echo "no program found for 'embedded' tests - skipped testing" ; \ fi - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=funcs1_ps --ps-protocol --suite=funcs_1 - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=funcs2 --suite=funcs_2 - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=rpl --suite=rpl - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=partitions --suite=parts - -if [ -d mysql-test/suite/nist ] ; then \ - cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --comment=NIST+normal --force --suite=nist ; \ - fi - -if [ -d mysql-test/suite/nist ] ; then \ - cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --comment=NIST+ps --force --suite=nist --ps-protocol ; \ - fi - -cd mysql-test ; MTR_BUILD_THREAD=auto \ - @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress # Re-enable the "jp" suite when bug#28563 is fixed # -cd mysql-test ; MTR_BUILD_THREAD=auto \ diff --git a/mysql-test/r/read_only_innodb.result b/mysql-test/r/read_only_innodb.result index d028e3cc207..690de085bf9 100644 --- a/mysql-test/r/read_only_innodb.result +++ b/mysql-test/r/read_only_innodb.result @@ -16,3 +16,33 @@ ERROR HY000: The MySQL server is running with the --read-only option so it canno set global read_only=0; drop table table_11733 ; drop user test@localhost; +GRANT CREATE, SELECT, DROP ON *.* TO test@localhost; +CREATE TABLE t1(a INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (0), (1); +SET GLOBAL read_only=1; +SELECT * FROM t1; +a +0 +1 +BEGIN; +SELECT * FROM t1; +a +0 +1 +COMMIT; +SET GLOBAL read_only=0; +FLUSH TABLES WITH READ LOCK; +SELECT * FROM t1; +a +0 +1 +BEGIN; +SELECT * FROM t1; +a +0 +1 +COMMIT; +UNLOCK TABLES; +DROP TABLE t1; +DROP USER test@localhost; +echo End of 5.1 tests diff --git a/mysql-test/suite/rpl/r/rpl_row_create_table.result b/mysql-test/suite/rpl/r/rpl_row_create_table.result index ebfb576c42d..c4cf8353bca 100644 --- a/mysql-test/suite/rpl/r/rpl_row_create_table.result +++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result @@ -417,3 +417,17 @@ Log_name Pos Event_type Server_id End_log_pos Info SELECT * FROM t2 ORDER BY a; a DROP TABLE t1,t2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(1); +CREATE TABLE t2 (a INT UNIQUE) ENGINE=INNODB SELECT * FROM t1; +ERROR 23000: Duplicate entry '1' for key 'a' +INSERT INTO t1 VALUES (2); +*** the proof of the fix: +select must show that the last insert performed on the slave *** +SELECT * FROM t1; +a +1 +1 +2 +DROP TABLE t1; +end of the tests diff --git a/mysql-test/suite/rpl/t/rpl_row_create_table.test b/mysql-test/suite/rpl/t/rpl_row_create_table.test index bfeb939f30f..e5cdfa4341a 100644 --- a/mysql-test/suite/rpl/t/rpl_row_create_table.test +++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test @@ -234,3 +234,30 @@ SELECT * FROM t2 ORDER BY a; connection master; DROP TABLE t1,t2; sync_slave_with_master; + +# +# bug#35762 Failing CREATE-SELECT produces bad binlog in row mode +# + +connection master; + +CREATE TABLE t1 (a INT); + +INSERT INTO t1 VALUES (1),(1); +--error ER_DUP_ENTRY +CREATE TABLE t2 (a INT UNIQUE) ENGINE=INNODB SELECT * FROM t1; +INSERT INTO t1 VALUES (2); + +sync_slave_with_master; +# connection slave; + +--echo *** the proof of the fix: +--echo select must show that the last insert performed on the slave *** +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +sync_slave_with_master; + + +--echo end of the tests diff --git a/mysql-test/t/read_only_innodb.test b/mysql-test/t/read_only_innodb.test index 76d9748aa60..f8c25fdee1d 100644 --- a/mysql-test/t/read_only_innodb.test +++ b/mysql-test/t/read_only_innodb.test @@ -41,3 +41,45 @@ set global read_only=0; drop table table_11733 ; drop user test@localhost; +disconnect con1; + +# +# Bug #35732: read-only blocks SELECT statements in InnoDB +# +# Test 1: read only mode +GRANT CREATE, SELECT, DROP ON *.* TO test@localhost; +connect(con1, localhost, test, , test); + +connection default; +CREATE TABLE t1(a INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (0), (1); +SET GLOBAL read_only=1; + +connection con1; +SELECT * FROM t1; +BEGIN; +SELECT * FROM t1; +COMMIT; + +connection default; +SET GLOBAL read_only=0; + +# +# Test 2: global read lock +# +FLUSH TABLES WITH READ LOCK; + +connection con1; +SELECT * FROM t1; +BEGIN; +SELECT * FROM t1; +COMMIT; + +connection default; +UNLOCK TABLES; +DROP TABLE t1; +DROP USER test@localhost; + +disconnect con1; + +--echo echo End of 5.1 tests diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index e2bdd668c0f..a33c4fcb9fa 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -433,7 +433,10 @@ ALTER TABLE db MODIFY Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NO # ALTER TABLE event DROP PRIMARY KEY; ALTER TABLE event ADD PRIMARY KEY(db, name); -ALTER TABLE event ADD sql_mode +# Add sql_mode column just in case. +ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion; +# Update list of sql_mode values. +ALTER TABLE event MODIFY sql_mode set('REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', diff --git a/sql/handler.cc b/sql/handler.cc index b334e003851..6099faa929f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -952,16 +952,21 @@ int ha_prepare(THD *thd) A helper function to evaluate if two-phase commit is mandatory. As a side effect, propagates the read-only/read-write flags of the statement transaction to its enclosing normal transaction. + + If we have at least two engines with read-write changes we must + run a two-phase commit. Otherwise we can run several independent + commits as the only transactional engine has read-write changes + and others are read-only. - @retval TRUE we must run a two-phase commit. Returned - if we have at least two engines with read-write changes. - @retval FALSE Don't need two-phase commit. Even if we have two - transactional engines, we can run two independent - commits if changes in one of the engines are read-only. + @retval 0 All engines are read-only. + @retval 1 We have the only engine with read-write changes. + @retval >1 More than one engine have read-write changes. + Note: return value might NOT be the exact number of + engines with read-write changes. */ static -bool +uint ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list, bool all) { @@ -998,7 +1003,7 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list, break; } } - return rw_ha_count > 1; + return rw_ha_count; } @@ -1061,25 +1066,8 @@ int ha_commit_trans(THD *thd, bool all) #ifdef USING_TRANSACTIONS if (ha_info) { - bool must_2pc; - - if (is_real_trans && wait_if_global_read_lock(thd, 0, 0)) - { - ha_rollback_trans(thd, all); - DBUG_RETURN(1); - } - - if ( is_real_trans - && opt_readonly - && ! (thd->security_ctx->master_access & SUPER_ACL) - && ! thd->slave_thread - ) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); - ha_rollback_trans(thd, all); - error= 1; - goto end; - } + uint rw_ha_count; + bool rw_trans; DBUG_EXECUTE_IF("crash_commit_before", abort();); @@ -1087,9 +1075,29 @@ int ha_commit_trans(THD *thd, bool all) if (is_real_trans) /* not a statement commit */ thd->stmt_map.close_transient_cursors(); - must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all); + rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all); + /* rw_trans is TRUE when we in a transaction changing data */ + rw_trans= is_real_trans && (rw_ha_count > 0); - if (!trans->no_2pc && must_2pc) + if (rw_trans && + wait_if_global_read_lock(thd, 0, 0)) + { + ha_rollback_trans(thd, all); + DBUG_RETURN(1); + } + + if (rw_trans && + opt_readonly && + !(thd->security_ctx->master_access & SUPER_ACL) && + !thd->slave_thread) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); + ha_rollback_trans(thd, all); + error= 1; + goto end; + } + + if (!trans->no_2pc && (rw_ha_count > 1)) { for (; ha_info && !error; ha_info= ha_info->next()) { @@ -1129,7 +1137,7 @@ int ha_commit_trans(THD *thd, bool all) tc_log->unlog(cookie, xid); DBUG_EXECUTE_IF("crash_commit_after", abort();); end: - if (is_real_trans) + if (rw_trans) start_waiting_global_read_lock(thd); } #endif /* USING_TRANSACTIONS */ diff --git a/sql/lock.cc b/sql/lock.cc index a0d6faa6604..675b94c2175 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1533,6 +1533,7 @@ void start_waiting_global_read_lock(THD *thd) if (unlikely(thd->global_read_lock)) DBUG_VOID_RETURN; (void) pthread_mutex_lock(&LOCK_global_read_lock); + DBUG_ASSERT(protect_against_global_read_lock); tmp= (!--protect_against_global_read_lock && (waiting_for_read_lock || global_read_lock_blocks_commit)); (void) pthread_mutex_unlock(&LOCK_global_read_lock); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 89038bacda3..d1e5c26912d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3720,7 +3720,7 @@ void select_create::abort() select_insert::abort(); thd->transaction.stmt.modified_non_trans_table= FALSE; reenable_binlog(thd); - + thd->binlog_flush_pending_rows_event(TRUE); if (m_plock) { diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 7f7674eefc9..5cbd85c62b4 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -341,7 +341,6 @@ BuildMySQL "--enable-shared \ %endif --with-archive-storage-engine \ --with-csv-storage-engine \ - --with-example-storage-engine \ --with-blackhole-storage-engine \ %if %{FEDERATED_BUILD} --with-federated-storage-engine \ @@ -373,13 +372,16 @@ BuildMySQL "--enable-shared \ --with-innodb \ %if %{CLUSTER_BUILD} --with-ndbcluster \ +%else + --without-ndbcluster \ %endif --with-archive-storage-engine \ --with-csv-storage-engine \ - --with-example-storage-engine \ --with-blackhole-storage-engine \ %if %{FEDERATED_BUILD} --with-federated-storage-engine \ +%else + --without-federated-storage-engine \ %endif --with-partition \ --with-embedded-server \