List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:November 20 2007 3:48pm
Subject:Re: bk commit into 5.1 tree (kostja:1.2607) BUG#12713
View as plain text  
Hi!

On Nov 14, konstantin@stripped wrote:
> ChangeSet@stripped, 2007-11-14 17:46:40+03:00, kostja@bodhi.(none) +9 -0
>   Bug#12713. This patch fixes the bug. No test cases, changeset comments, 
>   or review comments.
>   An intermediate commit for the passing test suite.

I've only looked at handler.cc, handler.h, and sql_class.h changes.
They looked ok to me.

The rest was, apparently, not related to commit/rollback changes, but
consisted of fixes for your earlier changesets.

see a couple of suggestions below, mostly about comments - what they
could clarify better.
 
> diff -Nrup a/sql/handler.cc b/sql/handler.cc
> --- a/sql/handler.cc	2007-10-30 22:35:11 +03:00
> +++ b/sql/handler.cc	2007-11-14 17:46:37 +03:00
> @@ -608,12 +608,13 @@ void trans_register_ha(THD *thd, bool al
>    else
>      trans= &thd->transaction.stmt;
>  
> -  for (ht=trans->ht; *ht; ht++)
> -    if (*ht == ht_arg)
> -      DBUG_VOID_RETURN;  /* already registered, return */
> +  ha_info= thd->ha_data[ht_arg->slot].ha_info +
> static_cast<unsigned>(all);

do you get a warning without this explicit cast ?

> +
> +  if (ha_info->ht)
> +    DBUG_VOID_RETURN; /* already registered, return */
> +
> +  ha_info->register_ha(trans, ht_arg);
>  
> -  trans->ht[trans->nht++]=ht_arg;
> -  DBUG_ASSERT(*ht == ht_arg);
>    trans->no_2pc|=(ht_arg->prepare==0);
>    if (thd->transaction.xid_state.xid.is_null())
>      thd->transaction.xid_state.xid.set(thd->query_id);
> @@ -669,9 +671,13 @@ int ha_prepare(THD *thd)
>  int ha_commit_trans(THD *thd, bool all)
>  {
>    int error= 0, cookie= 0;
> +  /*
> +    'all' means that this is either an explicit commit issued by
> +    user, or an implicit commit issued by a DDL.

you'd better add a comment explaining is_real_trans (a commit of a
transaction that makes the changes persistent, when is_real_trans==0,
it means we're at the end of the statement within transaction, and there
will be a "real" commit or rollback later)

> +  */
>    THD_TRANS *trans= all ? &thd->transaction.all :
> &thd->transaction.stmt;
> -  bool is_real_trans= all || thd->transaction.all.nht == 0;
> -  handlerton **ht= trans->ht;
> +  bool is_real_trans= all || thd->transaction.all.ha_list == 0;
> +  Ha_trx_info *ha_info= trans->ha_list;
>    my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
>    DBUG_ENTER("ha_commit_trans");
>  
> @@ -722,12 +728,26 @@ int ha_commit_trans(THD *thd, bool all)
>      if (is_real_trans)                          /* not a statement commit */
>        thd->stmt_map.close_transient_cursors();
>  
> -    if (!trans->no_2pc && trans->nht > 1)
> +    if (!trans->no_2pc && ha_info->next)
>      {
> -      for (; *ht && !error; ht++)
> +      for (; ha_info && !error; ha_info= ha_info->next)
>        {
>          int err;
> -        if ((err= (*(*ht)->prepare)(*ht, thd, all)))
> +        handlerton *ht= ha_info->ht;
> +        /**
> +          Perform a two-phase commit only if:

 perform a two-phase commit *in this storage engine* only if:

> +          - we're doing a DDL or
> +          - we're issuing a DML that has actually updated rows.

 actually updated rows *in this storage engine*

> +          In other cases, like read-only SELECT statements,
> +          we would like to save on two-phase commits and therefore
> +          avoid a potential disk sync of the binary log entailed by it.
> +        */
> +        if (!all &&
> +            (sql_command_flags[thd->lex->sql_command] & CF_DML)
> &&
> +            ha_info->is_trx_read_only())
> +          continue;
> +
> +        if ((err= ht->prepare(ht, thd, all)))
>          {
>            my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
>            error= 1;
> diff -Nrup a/sql/handler.h b/sql/handler.h
> --- a/sql/handler.h	2007-09-07 17:41:46 +04:00
> +++ b/sql/handler.h	2007-11-14 17:46:37 +03:00
> @@ -758,7 +758,57 @@ typedef struct st_thd_trans
>      saved value.
>    */
>    bool modified_non_trans_table;
> -} THD_TRANS;
> +
> +  void reset() { no_2pc= FALSE; modified_non_trans_table= FALSE; }
> +};
> +
> +
> +/**
> +  Either statement- or transaction- local thread-specific
> +  storage engine data.
> +
> +  If a storage engine participates in a statement/transaction,
> +  an instance of this class is present in
> +  thd->transaction.{stmt|all}.ha_list. The addition to ha_list
> +  is done by trans_register_ha.
> +
> +  When it's time to commit or rollback, each element of ha_list
> +  is used to access storage engine prepare/commit/rollback
> +  methods, and also to evaluate whether a full two phase commit
> +  is necessary.
> +*/
> +
> +struct Ha_trx_info
> +{
> +  /**
> +    Register this storage engine in the given transaction context.
> +  */
> +  void register_ha(THD_TRANS *trans, handlerton *ht_arg)
> +  { next= trans->ha_list; trans->ha_list= this; ht= ht_arg; flags= 0; }

please add a short comment that it's important to prepend to the list,
not to append. e.g. something like

     /**
       Register this storage engine in the given transaction context.

       note that new ha's are added to the *beginning* of the list,
       ha_rollback_to_savepoint() relies on it.
     */

> +
> +  /** Clear, prepare for reuse. */
> +  void reset() { next= NULL; ht= NULL; flags= 0; }
> +
> +  Ha_trx_info() { reset(); }
> +
> +  void set_trx_read_write() { flags|= (int) TRX_READ_WRITE; }
> +  bool is_trx_read_only() const { return !(flags & (int) TRX_READ_WRITE); }
> +public:
> +  /** public only to simplify access. Please use methods to assign. */

why not to use getters ?

> +  /** Auxiliary, used for ha_list management */
> +  Ha_trx_info *next;
> +  /**
> +    Although a given Ha_trx_info instance is currently always used
> +    for the same storage engine, 'ht' is not-NULL only when the
> +    corresponding storage is a part of a transaction.
> +  */
> +  handlerton *ht;
> +private:
> +  enum { TRX_READ_ONLY= 0, TRX_READ_WRITE= 1 };
> +  uchar      flags;
> +};
> +
> +
>  
>  enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
>  			 ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
Regards / Mit vielen Grüssen,
Sergei

-- 
   __  ___     ___ ____  __
  /  |/  /_ __/ __/ __ \/ /   Sergei Golubchik <serg@stripped>
 / /|_/ / // /\ \/ /_/ / /__  Principal Software Developer
/_/  /_/\_, /___/\___\_\___/  MySQL GmbH, Dachauer Str. 37, D-80335 München
       <___/                  Geschäftsführer: Kaj Arnö - HRB
München 162140
Thread
bk commit into 5.1 tree (kostja:1.2607) BUG#12713konstantin14 Nov
  • Re: bk commit into 5.1 tree (kostja:1.2607) BUG#12713Sergei Golubchik20 Nov
    • Re: bk commit into 5.1 tree (kostja:1.2607) BUG#12713Konstantin Osipov23 Nov