during EXPLAIN
Before the patch, send_eof() of some subclasses of
select_result (e.g., select_send::send_eof()) could
handle being called after an error had occured while others
could not. The methods that were not well-behaved would trigger
an ASSERT on debug builds. Release builds were not affected.
Consider the following query as an example for how the ASSERT
could be triggered:
A user without execute privilege on f() does
SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1;
resulting in "ERROR 42000: execute command denied to user..."
The server would end the query by calling send_eof(). The
fact that the error had occured would make the ASSERT trigger.
select_dumpvar::send_eof() was the offending method in the
bug report, but the problem also applied to other
subclasses of select_result. This patch uniforms send_eof()
of all subclasses of select_result to handle being called
after an error has occured.
mysql-test/r/not_embedded_server.result:
Added test for BUG#54812
mysql-test/t/not_embedded_server.test:
Added test for BUG#54812
sql/sql_class.cc:
send_eof() of all subclasses of select_result can now handle being
called after an error has occured.
sql/sql_insert.cc:
send_eof() of all subclasses of select_result can now handle being
called after an error has occured.
Also fix call to abort() in select_create::send_eof(), which was supposed to abort the result set, not terminate the server. This call to abort() should have been changed when the function was renamed from abort_result_set() but was forgotten. New test case added by BUG#54812 covered this line and terminated server.
sql/sql_prepare.cc:
send_eof() of all subclasses of select_result can now handle being
called after an error has occured.
sql/sql_update.cc:
send_eof() of all subclasses of select_result can now handle being
called after an error has occured.
2617.31.12, 2617.31.15, 2617.31.15, 2617.31.16, 2617.43.1
- initial changeset that introduced the fix for
Bug#989 and follow up fixes for all test suite failures
introduced in the initial changeset.
------------------------------------------------------------
revno: 2617.31.1
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Fri 2009-03-06 19:17:00 -0300
message:
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking
Currently the MySQL server does not keep metadata locks on
schema objects for the duration of a transaction, thus failing
to guarantee the integrity of the schema objects being used
during the transaction and to protect then from concurrent
DDL operations. This also poses a problem for replication as
a DDL operation might be replicated even thought there are
active transactions using the object being modified.
The solution is to defer the release of metadata locks until
a active transaction is either committed or rolled back. This
prevents other statements from modifying the table for the
entire duration of the transaction. This provides commitment
ordering for guaranteeing serializability across multiple
transactions.
- Incompatible change:
If MySQL's metadata locking system encounters a lock conflict,
the usual schema is to use the try and back-off technique to
avoid deadlocks -- this schema consists in releasing all locks
and trying to acquire them all in one go.
But in a transactional context this algorithm can't be utilized
as its not possible to release locks acquired during the course
of the transaction without breaking the transaction commitments.
To avoid deadlocks in this case, the ER_LOCK_DEADLOCK will be
returned if a lock conflict is encountered during a transaction.
Let's consider an example:
A transaction has two statements that modify table t1, then table
t2, and then commits. The first statement of the transaction will
acquire a shared metadata lock on table t1, and it will be kept
utill COMMIT to ensure serializability.
At the moment when the second statement attempts to acquire a
shared metadata lock on t2, a concurrent ALTER or DROP statement
might have locked t2 exclusively. The prescription of the current
locking protocol is that the acquirer of the shared lock backs off
-- gives up all his current locks and retries. This implies that
the entire multi-statement transaction has to be rolled back.
- Incompatible change:
FLUSH commands such as FLUSH PRIVILEGES and FLUSH TABLES WITH READ
LOCK won't cause locked tables to be implicitly unlocked anymore.
mysql-test/extra/binlog_tests/drop_table.test:
Add test case for Bug#989.
mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction.
mysql-test/include/mix1.inc:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction.
mysql-test/include/mix2.inc:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction.
mysql-test/r/flush_block_commit.result:
Update test case result (WL#4284).
mysql-test/r/flush_block_commit_notembedded.result:
Update test case result (WL#4284).
mysql-test/r/innodb.result:
Update test case result (WL#4284).
mysql-test/r/innodb_mysql.result:
Update test case result (WL#4284).
mysql-test/r/lock.result:
Add test case result for an effect of WL#4284/Bug#989
(all locks should be released when a connection terminates).
mysql-test/r/mix2_myisam.result:
Update test case result (effects of WL#4284/Bug#989).
mysql-test/r/not_embedded_server.result:
Update test case result (effects of WL#4284/Bug#989).
Add a test case for interaction of WL#4284 and FLUSH PRIVILEGES.
mysql-test/r/partition_innodb_semi_consistent.result:
Update test case result (effects of WL#4284/Bug#989).
mysql-test/r/partition_sync.result:
Temporarily disable the test case for Bug#43867,
which will be fixed by a subsequent backport.
mysql-test/r/ps.result:
Add a test case for effect of PREPARE on transactional
locks: we take a savepoint at beginning of PREAPRE
and release it at the end. Thus PREPARE does not
accumulate metadata locks (Bug#989/WL#4284).
mysql-test/r/read_only_innodb.result:
Update test case result (effects of WL#4284/Bug#989).
mysql-test/suite/binlog/r/binlog_row_drop_tbl.result:
Add a test case result (WL#4284/Bug#989).
mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result:
Update test case result (effects of WL#4284/Bug#989).
mysql-test/suite/binlog/r/binlog_stm_drop_tbl.result:
Add a test case result (WL#4284/Bug#989).
mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result:
Update test case result (effects of WL#4284/Bug#989).
mysql-test/suite/binlog/r/binlog_unsafe.result:
A side effect of Bug#989 -- slightly different table map ids.
mysql-test/suite/binlog/t/binlog_row_drop_tbl.test:
Add a test case for WL#4284/Bug#989.
mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test:
Add a test case for WL#4284/Bug#989.
mysql-test/suite/binlog/t/binlog_stm_row.test:
Update to the new state name. This
is actually a follow up to another patch for WL#4284,
that changes Locked thread state to Table lock.
mysql-test/suite/ndb/r/ndb_index_ordered.result:
Remove result for disabled part of the test case.
mysql-test/suite/ndb/t/disabled.def:
Temporarily disable a test case (Bug#45621).
mysql-test/suite/ndb/t/ndb_index_ordered.test:
Disable a part of a test case (needs update to
reflect semantics of Bug#989).
mysql-test/suite/rpl/t/disabled.def:
Disable tests made meaningless by transactional metadata
locking.
mysql-test/suite/sys_vars/r/autocommit_func.result:
Add a commit (Bug#989).
mysql-test/suite/sys_vars/t/autocommit_func.test:
Add a commit (Bug#989).
mysql-test/t/flush_block_commit.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction.
mysql-test/t/flush_block_commit_notembedded.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction.
Add a test case for transaction-scope locks and the global
read lock (Bug#989/WL#4284).
mysql-test/t/innodb.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction
(effects of Bug#989/WL#4284).
mysql-test/t/lock.test:
Add a test case for Bug#989/WL#4284.
mysql-test/t/not_embedded_server.test:
Add a test case for Bug#989/WL#4284.
mysql-test/t/partition_innodb_semi_consistent.test:
Replace TRUNCATE with DELETE, to not issue
an implicit commit of a transaction, and not depend
on metadata locks.
mysql-test/t/partition_sync.test:
Temporarily disable the test case for Bug#43867,
which needs a fix to be backported from 6.0.
mysql-test/t/ps.test:
Add a test case for semantics of PREPARE and transaction-scope
locks: metadata locks on tables used in PREPARE are enclosed into a
temporary savepoint, taken at the beginning of PREPARE,
and released at the end. Thus PREPARE does not effect
what locks a transaction owns.
mysql-test/t/read_only_innodb.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction
(Bug#989/WL#4284).
Wait for the read_only statement to actually flush tables before
sending other concurrent statements that depend on its state.
mysql-test/t/xa.test:
Fix test case to reflect the fact that transactions now hold
metadata locks for the duration of a transaction
(Bug#989/WL#4284).
sql/ha_ndbcluster_binlog.cc:
Backport bits of changes of ha_ndbcluster_binlog.cc
from 6.0, to fix the failing binlog test suite with
WL#4284. WL#4284 implementation does not work
with 5.1 implementation of ndbcluster binlog index.
sql/log_event.cc:
Release metadata locks after issuing a commit.
sql/mdl.cc:
Style changes (WL#4284).
sql/mysql_priv.h:
Rename parameter to match the name used in the definition (WL#4284).
sql/rpl_injector.cc:
Release metadata locks on commit (WL#4284).
sql/rpl_rli.cc:
Remove assert made meaningless, metadata locks are released
at the end of the transaction.
sql/set_var.cc:
Close tables and release locks if autocommit mode is set.
sql/slave.cc:
Release metadata locks after a rollback.
sql/sql_acl.cc:
Don't implicitly unlock locked tables. Issue a implicit commit
at the end and unlock tables.
sql/sql_base.cc:
Defer the release of metadata locks when closing tables
if not required to.
Issue a deadlock error if the locking protocol requires
that a transaction re-acquire its locks.
Release metadata locks when closing tables for reopen.
sql/sql_class.cc:
Release metadata locks if the thread is killed.
sql/sql_parse.cc:
Release metadata locks after implicitly committing a active
transaction, or after explicit commits or rollbacks.
sql/sql_plugin.cc:
Allocate MDL request on the stack as the use of the table
is contained within the function. It will be removed from
the context once close_thread_tables is called at the end
of the function.
sql/sql_prepare.cc:
The problem is that the prepare phase of the CREATE TABLE
statement takes a exclusive metadata lock lock and this can
cause a self-deadlock the thread already holds a shared lock
on the table being that should be created.
The solution is to make the prepare phase take a shared
metadata lock when preparing a CREATE TABLE statement. The
execution of the statement will still acquire a exclusive
lock, but won't cause any problem as it issues a implicit
commit.
After some discussions with stakeholders it has been decided that
metadata locks acquired during a PREPARE statement must be released
once the statement is prepared even if it is prepared within a multi
statement transaction.
sql/sql_servers.cc:
Don't implicitly unlock locked tables. Issue a implicit commit
at the end and unlock tables.
sql/sql_table.cc:
Close table and release metadata locks after a admin operation.
sql/table.h:
The problem is that the prepare phase of the CREATE TABLE
statement takes a exclusive metadata lock lock and this can
cause a self-deadlock the thread already holds a shared lock
on the table being that should be created.
The solution is to make the prepare phase take a shared
metadata lock when preparing a CREATE TABLE statement. The
execution of the statement will still acquire a exclusive
lock, but won't cause any problem as it issues a implicit
commit.
sql/transaction.cc:
Release metadata locks after the implicitly committed due
to a new transaction being started. Also, release metadata
locks acquired after a savepoint if the transaction is rolled
back to the save point.
The problem is that in some cases transaction-long metadata locks
could be released before the transaction was committed. This could
happen when a active transaction was ended by a "START TRANSACTION"
or "BEGIN" statement, in which case the metadata locks would be
released before the actual commit of the active transaction.
The solution is to defer the release of metadata locks to after the
transaction has been implicitly committed. No test case is provided
as the effort to provide one is too disproportional to the size of
the fix.
We didn't expect "error: no error", although this is
in fact a legitimate state (if something is erroneous
on the master, but not on the slave, e.g. INSERT fails
on master due to UNIQUE constraint which does not exist
on slave).
We now list the ignore for "0: no error" the same way
as any other ignore; moreover, if no or an empty
--slave-skip-errors is passed at start-up, we show
"OFF" instead of empty list, as intended. (The code
for that was there, but was only run for the empty-
argument case, even if it subsequently tested for
both conditions.)
mysql-test/r/not_embedded_server.result:
Show that passing no --slave-skip-errors results
in "OFF" being shown as the variable's value. This
test's "twin" (also not embedded, but setting
--slave-skip-errors in its -opt file) lives in
variables-notembbeded.test.
mysql-test/r/variables-notembedded.result:
Show that error-ignore 0 is handled just like any other
ignore. This test's "twin" (also not embedded, but not
setting --slave-skip-errors in its -opt file) lives in
not_embbeded_server.test.
mysql-test/t/not_embedded_server.test:
Show that passing no --slave-skip-errors results
in "OFF" being shown as the variable's value.
mysql-test/t/variables-notembedded-master.opt:
Show that error-ignore 0 is handled just like any other
ignore.
sql/slave.cc:
- set up error-ignore-info even if --slave-skip-errors
was not passed at start-up.
- handle error 0 just like any other error.
mysql-test/r/change_user.result:
Update test case result.
mysql-test/r/not_embedded_server.result:
Update test case result.
mysql-test/t/change_user.test:
Move newer (and better) version of the test case.
mysql-test/t/not_embedded_server.test:
Move this test case over to change_user.test
This version is deterministic.
Problem 1: not_embedded_server runs SELECT FROM I_S.PROCESSLIST near the beginning.
check_testcase executes a query to the server before that. There is a race here,
because there is no guarantee that the thread executing check_testcase's query is
finished.
Problem 2: The SELECT FROM I_S.PROCESSLIST doens't seem very useful in the test.
It's at least misplaced.
Fix to both problems: Comment out SELECT FROM I_S.PROCESSLIST.
mysql-test/t/not_embedded_server.test:
Commented out failing / useless test.
behave randomly with mysql_change_user.
The test case had to be moved into not_embedded_server.test file,
because SHOW GLOBAL STATUS does not work properly in embedded
server (see bug 34517).
BitKeeper/deleted/.del-change_user-master.opt:
Delete: mysql-test/t/change_user-master.opt
mysql-test/r/change_user.result:
Move test case for Bug#31222 to not_embedded_server.test.
mysql-test/r/not_embedded_server.result:
Move test case for Bug#31222 to not_embedded_server.test.
mysql-test/t/change_user.test:
Move test case for Bug#31222 to not_embedded_server.test.
mysql-test/t/not_embedded_server.test:
Move test case for Bug#31222 to not_embedded_server.test.
renamed. Some new THD proc_info states are new. Directories must be
encountered in make in a specific order, to have symlinks already set.
Move community-server-specific tests into own tests, so that we can
exempt them from testing on enterprise servers.
BitKeeper/deleted/.del-profiling.inc:
Delete: mysql-test/include/profiling.inc
BitKeeper/deleted/.del-profiling.require:
Delete: mysql-test/r/profiling.require
configure.in:
Set a new order of sql_client_dirs, so that the make directory traversal
doesn't miss symlink dependencies.
mysql-test/r/not_embedded_server.result:
Account for new "executing" state.
mysql-test/t/information_schema.test:
Move community-feature test to another test file.
mysql-test/t/profiling.test:
Make test more generic to community features.
sql/lex.h:
Add symbol lost in manual merge.
sql/mysql_priv.h:
Insert a preprocessor layer between setting the caller and the function
that sets the thread state, so we can get caller information.
sql/mysqld.cc:
Add new server variable "have_community_features".
sql/set_var.cc:
Add new server variable "have_community_features".
sql/sql_class.cc:
Insert a preprocessor layer between setting the caller and the function
that sets the thread state, so we can get caller information.
sql/sql_profile.cc:
Function name change, my_strndup()
sql/sql_profile.h:
Insert a preprocessor layer between setting the caller and the function
that sets the thread state, so we can get caller information.
mysql-test/include/have_community_features.inc:
New BitKeeper file ``mysql-test/include/have_community_features.inc''
mysql-test/r/have_community_features.require:
New BitKeeper file ``mysql-test/r/have_community_features.require''
mysql-test/r/variables+c.result:
New BitKeeper file ``mysql-test/r/variables+c.result''
mysql-test/t/variables+c.test:
New BitKeeper file ``mysql-test/t/variables+c.test''
into bk-internal.mysql.com:/data0/bk/mysql-5.1-wl3337
client/mysqltest.c:
Auto merged
libmysqld/Makefile.am:
Auto merged
mysql-test/mysql-test-run.pl:
Auto merged
mysql-test/r/events.result:
Auto merged
mysql-test/r/not_embedded_server.result:
Auto merged
mysql-test/t/events.test:
Auto merged
sql/CMakeLists.txt:
Auto merged
sql/Makefile.am:
Auto merged
sql/mysqld.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp_head.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.cc:
Auto merged
sql/table.h:
Auto merged
make test ignore NDB injector thread
mysql-test/r/not_embedded_server.result:
Use INFORMATION_SCHEMA for getting PROCESSLIST so we can exclude the
NDB Binlog Injector thread as it may/may not be running depending on
if --with-ndbcluster is specified to mysql-test-run
mysql-test/t/not_embedded_server.test:
Use INFORMATION_SCHEMA for getting PROCESSLIST so we can exclude the
NDB Binlog Injector thread as it may/may not be running depending on
if --with-ndbcluster is specified to mysql-test-run
event_scheduler_ng.cc/h is no more
BitKeeper/deleted/.del-event_scheduler_ng.cc~8896b89040dbc4f6:
Delete: sql/event_scheduler_ng.cc
BitKeeper/deleted/.del-event_scheduler_ng.h~1431af5b185376f:
Delete: sql/event_scheduler_ng.h
mysql-test/r/not_embedded_server.result:
fix test
sql/Makefile.am:
event_scheduler_ng.cc/h is no more
sql/event_queue.cc:
event_scheduler_ng.cc/h is no more
sql/event_queue.h:
event_scheduler_ng.cc/h is no more
sql/event_scheduler.cc:
event_scheduler_ng.cc/h is no more
sql/event_scheduler.h:
event_scheduler_ng.cc/h is no more
sql/events.cc:
event_scheduler_ng.cc/h is no more
sql/events.h:
event_scheduler_ng.cc/h is no more
mysql-test/r/not_embedded_server.result:
update result
mysql-test/r/sp-threads.result:
update result
sql/event_scheduler.h:
fix build error with SUN compiler
sql/mysqld.cc:
fix problem with --init-file which was expecting to be the only running
thread. nevertheless Events should be started as close as possible to the
place connections are handled.
The idea of the patch is to separate statement processing logic,
such as parsing, validation of the parsed tree, execution and cleanup,
from global query processing logic, such as logging, resetting
priorities of a thread, resetting stored procedure cache, resetting
thread count of errors and warnings.
This makes PREPARE and EXECUTE behave similarly to the rest of SQL
statements and allows their use in stored procedures.
This patch contains a change in behaviour:
until recently for each SQL prepared statement command, 2 queries
were written to the general log, e.g.
[Query] prepare stmt from @stmt_text;
[Prepare] select * from t1 <-- contents of @stmt_text
The chagne was necessary to prevent [Prepare] commands from being written
to the general log when executing a stored procedure with Dynamic SQL.
We should consider whether the old behavior is preferrable and probably
restore it.
This patch refixes Bug#7115, Bug#10975 (partially), Bug#10605 (various bugs
in Dynamic SQL reported before it was disabled).
mysql-test/r/not_embedded_server.result:
Since we don't want to log Dynamic SQL in stored procedures,
now the general log gets only one log entry per SQL statement.
mysql-test/r/sp-error.result:
- remove obsolete tests
- a better error message for the case when a stored procedure that
returns a result set is called from a function
mysql-test/r/trigger.result:
- a better error message for the case when a stored procedure that
returns a result set is called from a trigger
mysql-test/t/sp-error.test:
- a better error message for the case when a stored procedure that
returns a result set is called from a function.
- move the comment to its place (end of file).
mysql-test/t/trigger.test:
- a better error message for the case when a stored procedure that
returns a result set is called from a trigger
sql/item_func.cc:
- we need to pass sql_command explicitly to get_var_with_binlog, because
when creating a query for SQL prepared statement thd->lex->sql_command
points at SQLCOM_EXECUTE, which is not listed in the list of update
queries.
sql/log_event.h:
- remove an extra copy of the previous sentence
sql/mysql_priv.h:
- fix declarations of sql_prepare.cc API
sql/share/errmsg.txt:
- a new error message, when one attempts to execute a prepared statement
which is currently being executed (this can happen only in Dynamic SQL
at the moment).
sql/sp_head.cc:
- extend sp_multi_results_command to return different flags for a
command (and rename it)
- add support for SQLCOM_PREPARE,SQLCOM_EXECUTE, SQLCOM_DEALLOCATE
to sp_get_flags_for_command
- replace multiple boolean sp_head members with uint m_flags
- a fix for a crash when user variables are used in a stored procedure
and binlog is on. A temporary fix for Bug#12637 "SP crashes the server
if it has update query with user var & binlog is enabled", which actually
stands for stored functions: now instead of a crash we break
replication if a user variable is used in a stored function which
is executed in prelocked mode.
sql/sp_head.h:
- replace multiple boolean flags of sp_head with uint m_flags;
- add flag CONTAINS_DYNAMIC_SQL
- use this flag to error if a stored procedure with Dynamic SQL is
called from a function or trigger.
sql/sql_class.cc:
- Statement_map::insert should not delete a statement if it exists,
now it's done externally to be able to handle the case when the
statement being deleted is in use.
- remove extra code (free_list is already reset in free_items)
sql/sql_lex.cc:
- add lex->stmt_prepare_mode; we can't rely on thd->command any more,
because we don't reset it any more (Dynamic SQL requirement is that
PS are as little intrusive as possible).
sql/sql_lex.h:
- declare bool LEX::stmt_prepare_mode
sql/sql_parse.cc:
- move prepared statement code to sql_prepare.cc
- change declarations (refactored code)
- better error message when one attempts to use Dynamic SQL or a
stored procedure that returns a result set in a function or trigger.
sql/sql_prepare.cc:
- major refactoring to ensure PREPARE/EXECUTE commands do not reset global THD
state and allow their use in stored procedures.
- add Prepared_statement::flags and use it to ensure no recursive execution
of a prepared statement is possible
- better comments
sql/sql_yacc.yy:
- enable PREPARE/EXECUTE/DEALLOCATE in stored procedures
- produce an error message on attempt to use PREPARE/EXECUTE/DEALLOCATE
in a stored function or trigger
mysql-test/r/sp-dynamic.result:
- sp-dynamic.test results
mysql-test/t/sp-dynamic.test:
- a new test for PREPARE/EXECUTE/DEALLOCATE in stored procedures.
mysql-test/r/ps_grant.result:
Deallocate prepare statements
Moved test for 'show full processlist' to not_embedded_server.test becasue it's shouldn't be here and it could fail on a slow computer where previous connections has not yet disconnected
mysql-test/t/ps_grant.test:
Deallocate prepare statements
Moved test for 'show full processlist' to not_embedded_server.test becasue it's shouldn't be here and it could fail on a slow computer where previous connections has not yet disconnected
sql/sql_lex.cc:
Fixed typo
mysql-test/r/not_embedded_server.result:
New BitKeeper file ``mysql-test/r/not_embedded_server.result''
mysql-test/t/not_embedded_server.test:
New BitKeeper file ``mysql-test/t/not_embedded_server.test''
BitKeeper/etc/ignore:
added ndb/tools/ndb_config