FTWRL behavior on same connection
Affects | Status | Importance | Assigned to | Milestone | ||
---|---|---|---|---|---|---|
MySQL patches by Codership |
New
|
High
|
Alex Yurchenko | |||
5.5 |
New
|
High
|
Alex Yurchenko | |||
Percona XtraDB Cluster moved to https://jira.percona.com/projects/PXC | Status tracked in 5.6 | |||||
5.5 |
Fix Released
|
Undecided
|
Unassigned | |||
5.6 |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
FTWRL with mysql is no-op after first one in same connection.
=======
MySQL [(none)]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
=======
With WSREP it tries to resume the provider and then again pause
it
=======
2014-01-14 22:41:19 15515 [Note] WSREP: Provider paused at 527ab192-
2014-01-14 22:41:20 15515 [Note] WSREP: GRL was in block commit mode when entering make_global_
2014-01-14 22:41:20 15515 [Note] WSREP: Provider resumed.
2014-01-14 22:41:20 15515 [Note] WSREP: Provider paused at 527ab192-
=======
The fix for https:/
This happens because in Global_
-------
/*
If we didn't succeed lock_global_
make_
*/
#ifdef WITH_WSREP
if (m_mdl_
{
WSREP_
"make_
thd-
m_mdl_
wsrep_
wsrep-
m_state= GRL_ACQUIRED;
}
#endif /* WITH_WSREP */
if (m_state != GRL_ACQUIRED)
DBUG_RETURN(0);
-------
I think the check
if (m_state != GRL_ACQUIRED)
DBUG_RETURN(0);
should go earlier than the WSREP branch.
This is in turn because
in Global_
------
if (!m_state)
{
MDL_request mdl_request;
DBUG_ASSERT(! thd->mdl_
mdl_
if (thd->mdl_
DBUG_
m_mdl_
m_state= GRL_ACQUIRED;
}
/*
We DON'T set global_
tables are flushed (as the present function serves for FLUSH TABLES WITH
READ LOCK only). Doing things in this order is necessary to avoid
deadlocks (we must allow COMMIT until all tables are closed; we should not
forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
UPDATE and one does FLUSH TABLES WITH READ LOCK).
*/
DBUG_RETURN(0);
-------
GRL is not acquired if it has already been acquired.
Related branches
no longer affects: | codership-mysql |
Tested with:
=== modified file 'Percona- Server/ sql/lock. cc' Server/ sql/lock. cc 2013-02-12 21:54:12 +0000 Server/ sql/lock. cc 2014-01-15 11:04:10 +0000 read_lock( ), or if we already suceeded global_ read_lock_ block_commit( ), do nothing.
--- Percona-
+++ Percona-
@@ -1058,6 +1058,8 @@
If we didn't succeed lock_global_
make_
*/
+ if (m_state != GRL_ACQUIRED)
+ DBUG_RETURN(0);
#ifdef WITH_WSREP blocks_ commits_ lock)
if (m_mdl_
@@ -1072,8 +1074,6 @@
}
#endif /* WITH_WSREP */
- if (m_state != GRL_ACQUIRED)
- DBUG_RETURN(0);
mdl_ request. init(MDL_ key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);
Works as vanilla mysql now:
MySQL [test]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [test]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [test]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
MySQL [test]> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
It doesn't try to resume and then pause for every FTWRL on same
connection.
Note that this affects FTWRL issued only on same connection and
not other connections (for which it says - "[Warning] WSREP:
Attempt to lock an already locked monitor.").
For the same connection, a lock_global_ read_lock after FTWRL is a
no-op, so this makes FTWRL issued on same connection a no-op
after the first one.
The
#ifdef WITH_WSREP blocks_ commits_ lock) DEBUG(" GRL was in block commit mode when entering " global_ read_lock_ block_commit" ); >mdl_context. release_ lock(m_ mdl_blocks_ commits_ lock); blocks_ commits_ lock= NULL; locked_ seqno= WSREP_SEQNO_ UNDEFINED; >resume( wsrep);
if (m_mdl_
{
WSREP_
"make_
thd-
m_mdl_
wsrep_
wsrep-
m_state= GRL_ACQUIRED;
}
#endif /* WITH_WSREP */
fragment was added for https:/ /bugs.launchpad .net/codership- mysql/+ bug/847353