← Back to team overview

maria-developers team mailing list archive

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