List:Commits« Previous MessageNext Message »
From:Ingo Strüwing Date:July 19 2007 10:19am
Subject:Re: bk commit into 5.0 tree (kostja:1.2533) BUG#29431
View as plain text  
Hi Konstantin,

OK to push from me. Please see suggestions for improvement below.

konstantin@stripped wrote:
...
> ChangeSet@stripped, 2007-07-19 03:28:47+04:00, kostja@bodhi.(none) +1 -0
>   A fix for Bug#29431 killing an insert delayed thread causes crash
>   No test case, since the bug requires a stress case with 30 INSERT DELAYED
>   threads and 1 killer thread to repeat. The patch is verified
>   manually.
>   
>   The server that is running DELAYED inserts would deadlock itself
>   or crash under high load if some of the delayed threads were KILLed
>   in the meanwhile.
>   
>   The fix is to change internal lock acquisition order of delayed inserts
>   subsystem and to ensure that
>   Delayed_insert::table_list::db does not point to volatile memory in some 
>   cases.
>   For details, please see a comment for sql_insert.cc.
> 
>   sql/sql_insert.cc@stripped, 2007-07-19 03:28:45+04:00, kostja@bodhi.(none) +5 -6
>     A fix for Bug#29431 killing an insert delayed thread causes crash
...
>     delayed_get_table would:
...
>     - discover that the delayed thread was killed
>     - try to unlock() the delayed insert instance in memory and in 
>     Delayed_insert::unlock()

What do you mean with "and in" here? Trying to unlock() means to call
Delayed_insert::unlock() right?

Ah. You probably mean:

    - try to unlock() the delayed insert instance
    - in Delayed_insert::unlock() we do:
      * lock LOCK_delayed_insert
      ...

>      * lock LOCK_delayed_insert
>      * decrease locks_in_memory and discover it's 0

...
>     As a side note, the whole concept of two locks - LOCK_delayed_insert
>     and LOCK_delayed_create is redundant, and we only need one of them
>     to protect the global delayed threads list.
>     As is redundant the concept of locks_in_memory, since we already
>     have another counter with similar semantics - tables_in_use, both
>     of them are devoted to counting the number of producers for a given
>     consumer (delayed insert thread), only at different stages of
>     producer-consumer relationship.
>     'dead' and 'status' variables in Delayed_insert are redundant too,
>     since there is already 'di->thd.killed' and di->stacked_inserts.
>     This redundancy made it hard to locate the bug, however the fix itself
>     luckily is simple.

Agree. But is a changeset the right place to add such note? Wouldn't a
TODO comment in the code be more appropriate? Or a worklog entry/feature
request?

I would like to add the confusing naming of variables. We should always
call a Delayed_insert object 'di', not 'tmp'.

...
>     3) The fix in find_handler is pure safety - we needn't assume that
>     Delayed_insert object already has a table opened at the point it is
>     present in the delayed insert list, although now it's always the case.

I agree with the belonging change, but disagree with "now it's always
the case". Moving the list append to the client doesn't change that a di
object is added to the list only when it was opened. The same was true
before due to the enclosing LOCK_delayed_create.

However, a terminating delayed thread closes the table before unlinking
di from the list. Your patch doesn't change this. So find_handler()
could see a closed table in both cases.

> 
> diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
> --- a/sql/sql_insert.cc	2007-07-08 23:02:59 +04:00
> +++ b/sql/sql_insert.cc	2007-07-19 03:28:45 +04:00
> @@ -1706,7 +1706,7 @@ Delayed_insert *find_handler(THD *thd, T
>    while ((tmp=it++))
>    {
>      if (!strcmp(tmp->thd.db,table_list->db) &&

I suggest to write strcmp(table_list->db, tmp->table_list.db) here. This
would make it more symmetric with the next line. Having argument and tmp
on different sides in both compares and using tmp->thd in one line, but
tmp->table_list in the other, looks like an attempt to maximize
confusion of a reader.

> -	!strcmp(table_list->table_name,tmp->table->s->table_name))
> +	!strcmp(table_list->table_name, tmp->table_list.table_name))

...
>        tmp->table_list= *table_list;			// Needed to open table

I'd add here: /* Replace volatile strings with local copies. */

>        tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query;
> +      tmp->table_list.db= tmp->thd.db;

...

Regards
Ingo
-- 
Ingo Strüwing, Senior Software Developer
MySQL GmbH, Radlkoferstr. 2, D-81373 München
Geschäftsführer: Kaj Arnö - HRB München 162140
Thread
bk commit into 5.0 tree (kostja:1.2533) BUG#29431konstantin19 Jul
  • Re: bk commit into 5.0 tree (kostja:1.2533) BUG#29431Ingo Strüwing19 Jul
    • Re: bk commit into 5.0 tree (kostja:1.2533) BUG#29431Konstantin Osipov19 Jul