Commit 3995b06b authored by unknown's avatar unknown

Don't use row level logging on optimize or repair table.

(Fixes core dump in rpl_failed_optimize.test)
Ensure we end active transcations if we do an admin command (like optimize, repair etc)


mysql-test/extra/rpl_tests/rpl_failed_optimize.test:
  Added extra test + drop of table at end of test
mysql-test/lib/mtr_report.pl:
  Fail if mysqld asserts or prints stack
mysql-test/mysql-test-run.sh:
  Fail if mysqld asserts or prints stack
mysql-test/r/exampledb.result:
  Cleanup of events_tests (as this caused a lot of problems if it didn't work)
mysql-test/r/innodb.result:
  Extra test to see that we can do an optimize table on an active transaction
mysql-test/r/rpl_failed_optimize.result:
  Added extra test + drop of table at end of test
mysql-test/t/exampledb.test:
  Cleanup of events_tests (as this caused a lot of problems if it didn't work)
mysql-test/t/innodb.test:
  Extra test to see that we can do an optimize table on an active transaction
sql/handler.cc:
  Don't use row level logging on optimize or repair table.
sql/log.cc:
  Simplify code (no logic changes)
sql/mysql_priv.h:
  Added prototype
sql/sql_base.cc:
  Better name for define
sql/sql_class.cc:
  Indentation fix
sql/sql_parse.cc:
  Make end_active_trans() global
sql/sql_table.cc:
  Ensure we end active transcations if we do an admin command (like optimize, repair etc)
parent d1b6779a
......@@ -17,3 +17,8 @@ OPTIMIZE TABLE non_existing;
sync_slave_with_master;
# End of 4.1 tests
connection master;
select * from t1;
commit;
drop table t1;
......@@ -218,7 +218,8 @@ sub mtr_report_stats ($) {
# We report different types of problems in order
foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x",
"InnoDB: Warning", "missing DBUG_RETURN",
"mysqld: Warning")
"mysqld: Warning",
"Attempting backtrace", "Assertion .* failed" )
{
foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
{
......@@ -232,7 +233,8 @@ sub mtr_report_stats ($) {
# Skip some non fatal warnings from the log files
if ( /Warning:\s+Table:.* on (delete|rename)/ or
/Warning:\s+Setting lower_case_table_names=2/ or
/Warning:\s+One can only use the --user.*root/ )
/Warning:\s+One can only use the --user.*root/ or
/InnoDB: Warning: we did not need to do crash recovery/)
{
next; # Skip these lines
}
......
......@@ -1073,13 +1073,13 @@ report_stats () {
#
$RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp
# Remove some non fatal warnings from the log files
$SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
$SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' -e 's|InnoDB: Warning: we did not need to do crash recovery||g' \
$MY_LOG_DIR/*.err \
| $SED -e 's!Warning: Table:.* on rename!!g' \
> $MY_LOG_DIR/warnings.tmp
# Find errors
for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning"
for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning" "Attempting backtrace" "Assertion .* failed"
do
if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then
......
drop database if exists events_test;
drop database if exists events_test2;
drop table if exists t1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
......
......@@ -3457,3 +3457,10 @@ a
drop table t2, t1;
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
ERROR HY000: The used table type doesn't support SPATIAL indexes
CREATE TABLE t1 ( a int ) ENGINE=innodb;
BEGIN;
INSERT INTO t1 VALUES (1);
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
DROP TABLE t1;
......@@ -18,3 +18,8 @@ Table Op Msg_type Msg_text
test.non_existing optimize error Table 'test.non_existing' doesn't exist
Warnings:
Error 1146 Table 'test.non_existing' doesn't exist
select * from t1;
a
1
commit;
drop table t1;
......@@ -5,6 +5,10 @@
-- source include/have_exampledb.inc
--disable_warnings
# Clean up if event's test fails
drop database if exists events_test;
drop database if exists events_test2;
drop table if exists t1;
--enable_warnings
......
......@@ -2500,3 +2500,13 @@ drop table t2, t1;
#
--error ER_TABLE_CANT_HANDLE_SPKEYS
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
#
# Test optimize on table with open transaction
#
CREATE TABLE t1 ( a int ) ENGINE=innodb;
BEGIN;
INSERT INTO t1 VALUES (1);
OPTIMIZE TABLE t1;
DROP TABLE t1;
......@@ -3264,10 +3264,11 @@ int handler::ha_external_lock(THD *thd, int lock_type)
locking combined with row-based replication needs to be looked
over. Ideally, no such special handling should be needed.
*/
switch (thd->lex->sql_command)
{
switch (thd->lex->sql_command) {
case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE:
case SQLCOM_OPTIMIZE:
case SQLCOM_REPAIR:
DBUG_RETURN(0);
default:
break;
......
......@@ -2879,23 +2879,27 @@ bool MYSQL_LOG::write(Log_event *event_info)
binlog_trx_data *const trx_data=
(binlog_trx_data*) thd->ha_data[binlog_hton.slot];
IO_CACHE *trans_log= &trx_data->trans_log;
bool trans_log_in_use= my_b_tell(trans_log) != 0;
if (event_info->get_cache_stmt() && !my_b_tell(trans_log))
if (event_info->get_cache_stmt() && !trans_log_in_use)
trans_register_ha(thd,
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN),
(thd->options &
(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)),
&binlog_hton);
if (event_info->get_cache_stmt() || my_b_tell(trans_log))
if (event_info->get_cache_stmt() || trans_log_in_use)
{
DBUG_PRINT("info", ("Using trans_log"));
file= trans_log;
}
/*
Note: as Mats suggested, for all the cases above where we write to
TODO as Mats suggested, for all the cases above where we write to
trans_log, it sounds unnecessary to lock LOCK_log. We should rather
test first if we want to write to trans_log, and if not, lock
LOCK_log. TODO.
LOCK_log.
*/
}
#endif
DBUG_PRINT("info",("event type=%d",event_info->get_type_code()));
DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
/*
No check for auto events flag here - this write method should
......
......@@ -558,6 +558,7 @@ enum enum_mysql_completiontype {
};
bool begin_trans(THD *thd);
bool end_active_trans(THD *thd);
int end_trans(THD *thd, enum enum_mysql_completiontype completion);
Item *negate_expression(THD *thd, Item *expr);
......
......@@ -288,13 +288,13 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (!(share= alloc_table_share(table_list, key, key_length)))
{
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
DBUG_RETURN(0);
}
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
// We need a write lock to be able to add a new entry
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&LOCK_open);
......@@ -331,19 +331,19 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (my_hash_insert(&table_def_cache, (byte*) share))
{
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
(void) pthread_mutex_unlock(&share->mutex);
#endif
free_table_share(share);
DBUG_RETURN(0); // return error
}
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (open_table_def(thd, share, db_flags))
{
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
/*
No such table or wrong table definition file
Lock first the table cache and then the mutex.
......@@ -372,7 +372,7 @@ found:
/* We must do a lock to ensure that the structure is initialized */
(void) pthread_mutex_lock(&share->mutex);
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (share->error)
......@@ -540,7 +540,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
DBUG_VOID_RETURN;
#ifdef NOT_YET
#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
if (to_be_deleted)
{
/*
......@@ -1069,7 +1069,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
handled either before writing a query log event (inside
binlog_query()) or when preparing a pending event.
*/
thd->binlog_flush_pending_rows_event(true);
thd->binlog_flush_pending_rows_event(TRUE);
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
......
......@@ -2688,8 +2688,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
DBUG_ENTER("THD::binlog_query");
DBUG_ASSERT(query && mysql_bin_log.is_open());
switch (qtype)
{
switch (qtype) {
case THD::MYSQL_QUERY_TYPE:
/*
Using this query type is a conveniece hack, since we have been
......
......@@ -137,7 +137,7 @@ static void unlock_locked_tables(THD *thd)
}
static bool end_active_trans(THD *thd)
bool end_active_trans(THD *thd)
{
int error=0;
DBUG_ENTER("end_active_trans");
......@@ -2961,8 +2961,7 @@ end_with_restore_list:
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
goto error;
else
res = mysql_create_index(thd, first_table, lex->key_list);
res= mysql_create_index(thd, first_table, lex->key_list);
break;
#ifdef HAVE_REPLICATION
......@@ -3069,18 +3068,16 @@ end_with_restore_list:
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
goto error;
else
{
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
first_table, lex->create_list,
lex->key_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->duplicates, lex->ignore, &lex->alter_info,
1);
}
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
first_table, lex->create_list,
lex->key_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->duplicates, lex->ignore, &lex->alter_info,
1);
break;
}
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
......@@ -3207,7 +3204,7 @@ end_with_restore_list:
check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_analyze_table(thd, first_table, &lex->check_opt);
res= mysql_analyze_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
......@@ -3512,8 +3509,7 @@ end_with_restore_list:
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
else
res = mysql_drop_index(thd, first_table, &lex->alter_info);
res= mysql_drop_index(thd, first_table, &lex->alter_info);
break;
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
......
......@@ -3898,6 +3898,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
int result_code;
DBUG_ENTER("mysql_admin_table");
if (end_active_trans(thd))
DBUG_RETURN(1);
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Op", 10));
......@@ -3948,6 +3950,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
switch ((*prepare_func)(thd, table, check_opt)) {
case 1: // error, message written to net
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
continue;
case -1: // error, message could be written to net
......@@ -3989,6 +3992,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
View opening can be interrupted in the middle of process so some
tables can be left opening
*/
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
if (protocol->write())
goto err;
......@@ -4013,6 +4017,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name);
protocol->store(buff, length, system_charset_info);
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
......@@ -4058,6 +4063,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
(table->table->file->ha_check_for_upgrade(check_opt) ==
HA_ADMIN_NEEDS_ALTER))
{
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
......@@ -4144,6 +4150,7 @@ send_result_message:
"try with alter", so here we close the table, do an ALTER TABLE,
reopen the table and do ha_innobase::analyze() on it.
*/
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
......@@ -4151,6 +4158,7 @@ send_result_message:
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
reenable_binlog(thd);
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
{
......@@ -4238,6 +4246,7 @@ send_result_message:
query_cache_invalidate3(thd, table->table, 0);
}
}
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
......@@ -4246,7 +4255,9 @@ send_result_message:
send_eof(thd);
DBUG_RETURN(FALSE);
err:
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
......@@ -4701,7 +4712,9 @@ mysql_discard_or_import_tablespace(THD *thd,
if (error)
goto err;
write_bin_log(thd, FALSE, thd->query, thd->query_length);
err:
ha_autocommit_or_rollback(thd, error);
close_thread_tables(thd);
thd->tablespace_op=FALSE;
......@@ -6388,7 +6401,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
}
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
List<Item> field_list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment