maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10192
Re: [Commits] 5f02c66: MDEV-11227 - mysqlimport -l doesn't issue UNLOCK TABLES
Hi Sergei,
Thanks for your feedback. Answers inline.
On Thu, Dec 15, 2016 at 02:23:03PM +0100, Sergei Golubchik wrote:
> Hi, Sergey!
>
> On Dec 13, Sergey Vojtovich wrote:
> > revision-id: 5f02c661f3d30baf08071acad29cef40fad0739c (mariadb-10.2.2-225-g5f02c66)
> > parent(s): 65b4d7457e40ee25302d2df28b0d200ff59d9e6d
> > committer: Sergey Vojtovich
> > timestamp: 2016-12-13 16:17:49 +0400
> > message:
> >
> > MDEV-11227 - mysqlimport -l doesn't issue UNLOCK TABLES
> >
> > Implementation of MDEV-7660 introduced unwanted incompatible change:
> > modifications under LOCK TABLES with autocommit enabled are rolled back on
> > disconnect. Previously everything was committed, because LOCK TABLES didn't
> > adjust autocommit setting.
>
> Thanks, very helpful comment (that I didn't quote in my reply for
> brevity)!
>
> Few questions below:
>
> > diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
> > index dea16c8..30fb694 100644
> > --- a/mysql-test/t/delayed.test
> > +++ b/mysql-test/t/delayed.test
> > @@ -319,7 +319,7 @@ drop table if exists t1;
> > --enable_warnings
> > create table t1 (a int, b int);
> > insert into t1 values (1,1);
> > -lock table t1 read;
> > +lock table t1 read local;
>
> why?
This is remnant of intermediate patch, when MDL_SHARED_READ_ONLY was acquired for
MyISAM too. It'd block subsequent "insert delayed" much earlier, making this test
useless.
I reverted this change. Thanks for spotting!
>
> > connect (update,localhost,root,,);
> > connection update;
> > --send insert delayed into t1 values (2,2);
> > diff --git a/sql/mdl.h b/sql/mdl.h
> > index 7d659af..d77c07c 100644
> > --- a/sql/mdl.h
> > +++ b/sql/mdl.h
> > @@ -196,6 +196,12 @@ enum enum_mdl_type {
> > */
> > MDL_SHARED_UPGRADABLE,
> > /*
> > + A shared metadata lock for cases when we need to read data from table
> > + and block all concurrent modifications to it (for both data and metadata).
> > + Used by LOCK TABLES READ statement.
> > + */
> > + MDL_SHARED_READ_ONLY,
>
> Hmm, stronger than MDL_SHARED_WRITE? All read locks were
> before write locks until now. Why is that changed?
I don't think your statement is completely valid: there's MDL_SHARED_NO_WRITE
(which is data read lock) after MDL_SHARED_READ_ONLY.
Also I don't completely understand how to evalutate strength of MDL_SHARED_*
locks by their position. They all do different things and have rather complex
compatibility and weight matrices.
This position was chosen by MySQL. I can only guess that they want to keep locks
up to SW to be used by DML and locks starting with SU used by DDL or LOCK TABLES.
>
> > + /*
> > An upgradable shared metadata lock which blocks all attempts to update
> > table data, allowing reads.
> > A connection holding this kind of lock can read table metadata and read
> > diff --git a/sql/sql_base.cc b/sql/sql_base.cc
> > index 1ca7e9c..d3f4517 100644
> > --- a/sql/sql_base.cc
> > +++ b/sql/sql_base.cc
> > @@ -1496,6 +1496,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
> > to general/slow log would be disabled in read only transactions.
> > */
> > if (table_list->mdl_request.type >= MDL_SHARED_WRITE &&
> > + table_list->mdl_request.type != MDL_SHARED_READ_ONLY &&
>
> if you're going to keep read and write locks mixed,
> then I'd suggest to move this condition into a small inline helper,
> like table_list->mdl_request.is_write_lock(). it's used few times
> already in this very file and there will be only one place to change
> if we'll need to add, say, MDL_SHARED_WRITE_LOW_PRIO
I can merge this from MySQL, it is called is_write_lock_request() there. In fact
MySQL didn't have to change this condition for MDL_SHARED_WRITE_LOW_PRIO.
>
> > thd->tx_read_only &&
> > !(flags & (MYSQL_LOCK_LOG_TABLE | MYSQL_OPEN_HAS_MDL_LOCK)))
> > {
> > diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
> > index 6dc9192..0d740bb 100644
> > --- a/sql/sql_parse.cc
> > +++ b/sql/sql_parse.cc
> > @@ -2728,27 +2728,76 @@ bool sp_process_definer(THD *thd)
> > static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
> > {
> > Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
> > + MDL_deadlock_and_lock_abort_error_handler deadlock_handler;
> > + MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
> > uint counter;
> > TABLE_LIST *table;
> >
> > thd->in_lock_tables= 1;
> >
> > +retry:
> > +
> > if (open_tables(thd, &tables, &counter, 0, &lock_tables_prelocking_strategy))
> > goto err;
> >
> > - /*
> > - We allow to change temporary tables even if they were locked for read
> > - by LOCK TABLES. To avoid a discrepancy between lock acquired at LOCK
> > - TABLES time and by the statement which is later executed under LOCK TABLES
> > - we ensure that for temporary tables we always request a write lock (such
> > - discrepancy can cause problems for the storage engine).
> > - We don't set TABLE_LIST::lock_type in this case as this might result in
> > - extra warnings from THD::decide_logging_format() even though binary logging
> > - is totally irrelevant for LOCK TABLES.
> > - */
> > for (table= tables; table; table= table->next_global)
> > - if (!table->placeholder() && table->table->s->tmp_table)
> > - table->table->reginfo.lock_type= TL_WRITE;
> > + {
> > + if (!table->placeholder())
> > + {
> > + if (table->table->s->tmp_table)
> > + {
> > + /*
> > + We allow to change temporary tables even if they were locked for read
> > + by LOCK TABLES. To avoid a discrepancy between lock acquired at LOCK
> > + TABLES time and by the statement which is later executed under LOCK
> > + TABLES we ensure that for temporary tables we always request a write
> > + lock (such discrepancy can cause problems for the storage engine).
> > + We don't set TABLE_LIST::lock_type in this case as this might result
> > + in extra warnings from THD::decide_logging_format() even though
> > + binary logging is totally irrelevant for LOCK TABLES.
> > + */
> > + table->table->reginfo.lock_type= TL_WRITE;
> > + }
> > + else if (table->mdl_request.type == MDL_SHARED_READ &&
> > + ! table->prelocking_placeholder &&
> > + table->table->file->lock_count() == 0)
> > + {
> > + /*
> > + In case when LOCK TABLE ... READ LOCAL was issued for table with
> > + storage engine which doesn't support READ LOCAL option and doesn't
> > + use THR_LOCK locks we need to upgrade weak SR metadata lock acquired
> > + in open_tables() to stronger SRO metadata lock.
> > + This is not needed for tables used through stored routines or
> > + triggers as we always acquire SRO (or even stronger SNRW) metadata
> > + lock for them.
> > + */
> > + deadlock_handler.init();
> > + thd->push_internal_handler(&deadlock_handler);
> > +
> > + bool result= thd->mdl_context.upgrade_shared_lock(
> > + table->table->mdl_ticket,
> > + MDL_SHARED_READ_ONLY,
> > + thd->variables.lock_wait_timeout);
> > +
> > + thd->pop_internal_handler();
> > +
> > + if (deadlock_handler.need_reopen())
> > + {
> > + /*
> > + Deadlock occurred during upgrade of metadata lock.
> > + Let us restart acquring and opening tables for LOCK TABLES.
>
> will you use MDL_SHARED_READ_ONLY right away when retrying?
> or it'll do the upgrade thing again?
Upgrade thing again, which is farily stupid. That's how it was in original code
and I didn't change it in a hurry.
Thanks,
Sergey
Follow ups
References