← Back to team overview

maria-developers team mailing list archive

Re: [Commits] 5f02c66: MDEV-11227 - mysqlimport -l doesn't issue UNLOCK TABLES

 

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?

>  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?

> +  /*
>      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

>        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?

> +          */
> +          close_tables_for_reopen(thd, &tables, mdl_savepoint);
> +          if (thd->open_temporary_tables(tables))
> +            goto err;
> +          goto retry;
> +        }
> +
> +        if (result)
> +          goto err;
> +      }
> +    }
> +  }
>  
>    if (lock_tables(thd, tables, counter, 0) ||
>        thd->locked_tables_list.init_locked_tables(thd))


Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx


Follow ups