WL#4284: Transactional DDL locking

Affects: Server-6.0 — Status: Complete — Priority: Medium

Split from WL#3726.
Implement transaction-long metadata locks. I.e. if a table is used in a
transaction, a metadata lock should be kept for this table until the transaction
is committed. This will prevent concurrent transactions from issuing a DDL
against this table. Necessary to fix BUG#989 If DROP TABLE while there's an
active transaction, wrong binlog order
In order to ensure transaction serializability, 
the server must not allow a concurrent connection to perform a DDL
statement on a table that is used in an uncompleted transaction.

Currently, for each table used in a statement, the server
acquires a shared metadata lock till the end of the statement.
When the statement is complete, the shared metadata lock is released.
A simple deadlock avoidance technique is employed to address the
problem of deadlocks in case of a lock conflict (see
http://forge.mysql.com/wiki/MySQL_Internals_Data_and_meta-data_locking for
details).

In order to ensure serializability, the server must defer the
release of metadata locks from the end of a statement till the end
of the encompassing transaction.

For a statement that doesn't start a transaction, e.g. a statement
on a non-transactional table/tables, this brings no change.

For a connection that runs in autocommit mode, the change also has
no effect.

Since each DDL statement commits the transaction, if any, in the
beginning, the change has no effect on lock conflicts between
concurrent DDL statements.

The other class of conflicts is between DDL and DML statements.
When a connection doesn't use autocommit and utilizes
multi-statement transactions, a new scenario
of lock conflicts is introduced. A conflict may happen between
the acquirer of a shared lock and a concurrent DDL, at the time
when the acquirer has executed several statements and possibly
modified or retrieved data.

Let's consider an example.

Transaction 1 modifies 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 till COMMIT, in
order 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
may 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.
For a multiple-statement scenario that implies that the entire
multi-statement transaction has to be rolled back.
Indeed, imagine that the concurrent connection issued
RENAME t2 to t3, t1 to t2, t3 to t1, rather than a simple ALTER.

In that case it will have acquired an exclusive lock on t2 at the
moment it encounters that t1 is locked in shared mode, and the
owner is not about to give away its locks.
Unless the DML transaction back off, a deadlock is unavoidable.

In future we may consider implementing a deadlock detection
algorithm that would allow us to detect the scenario described
above while allowing for other scenarios of lock conflicts.

One possible solution is given in Appendix A.

The scope of this task, however, is to simply abort the
transaction that attempts to acquire a shared lock.
Note, that the abortion only takes place if the transaction has
executed statements -- in other words, has acquired shared
metadata locks that ought to be released. If a lock conflict
happens in the first statement of the transaction, the locking
algorithm back off and retries as before.

If a user has set a savepoint, ROLLBACK TO SAVEPOINT should release
all metadata locks acquired after the savepoint has been set.

Apart from these two changes, the locking protocol should be left
intact.

Appendix A: a possible approach to deadlock detection
-----------------------------------------------------

If a shared/exclusive lock conflict occurs when attempting to acquire an
exclusive lock, a "pending exclusive" lock is placed instead.
This lock is "upgraded" to exclusive when all transactions
that own the conflicting lock have committed.
Existence of a pending exclusive lock prevents all new transactions
from acquiring the lock: they back off. Existing transaction, still,
can proceed, as long as new locks that they attempt to acquire do
not lead to deadlocks.
This latter fact can be checked easily by maintaining the list of
waiters on a given lock, and checking if some transaction is
present twice in the list.
Extend the metadata locking subsystem to keep metadata locks till the
end of a transaction.

Changes to existing APIs:

- none

Changed files and functions:

1) Introduce ha_in_transaction() that would return TRUE
if there is a started transaction in a given connection.
2) Store metadata locks in transaction memory root, rather than
statement memory root.
3) Modify close_thread_tables() to call mdl_release_locks() only
if we're outside the context of some transaction. Since
close_thread_tables() is called after each statement,
including COMMIT and ROLLBACK, that will ensure that metadata
locks are released automatically whenever a transaction has
either ended automatically, or was committed/aborted
manually.

BEGIN word is a no-op at MySQL. Operations on non-transactional
engines do not start a transaction either. Therefore, for
statements that use non-transactional tables outside the
context of some transaction, locks will be released at the end of each
statement, just like before.

3) Modify open_table() to raise rollback the transaction and
return ER_LOCK_DEADLOCK error in case of a shared/exclusive
lock conflict in a non-first statement of a transaction.

4) Modify ha_savepoint() to remember, and ha_rollback_to_savepoint()
to rollback to the remembered set of metadata locks.

Effect on LOCK TABLES TRANSACTIONAL

Effect on other statements

None

Bug reports:
BUG#989 If DROP TABLE while there's an active transaction, wrong binlog order
BUG#12347 InnoDB: DROP TABLE ignores locks
BUG#39945 "WITH CONSISTENT SNAPSHOT" does not isolate against table changes
(i.e. RENAME)


You must be logged in to tag this worklog

Phase three: check that the test code does what the comments say, check that the results are as stated in high-level specification. Done.

Phase four: put cycle counter functions in server code. Done. Phase four took place as part of WL#2360 work.

management degree AND Fire Science degree AND Advertising degree

I'm going to download and test your app. I looks very interesting... Online history degree AND Engineering degree

Votes

Not yet rated.
You must be logged in to vote.

Watches

0 members are watching this worklog
You must be logged in to track this worklog.

Provide Feedback

Please note:
HTML will be purified, but we allow for a number of HTML tags so that you have the flexibility to decorate your comment text to some extent. The comments allow the following HTML tags:

strong, b, em, blockquote, a, code, pre

To put code into your comment, simply encapsulate your code with
[code language="XXX"][/code], where XXX is any common language, for instance "PHP", "SQL", "C", etc.



You must be logged in to comment