• unknown's avatar
    Fix for bug #12739 "Deadlock in multithreaded environment during creating/ · dd02b98d
    unknown authored
    droping trigger on InnoDB table".
    
    Deadlock occured in cases when we were trying to create two triggers for
    the same InnoDB table concurrently and both threads were able to reach
    close_cached_table() simultaneously. Bugfix implements new approach to
    table locking and table cache invalidation during creation/dropping
    of trigger.
    
    No testcase is supplied since bug was repeatable only under high concurrency.
    
    
    sql/mysql_priv.h:
      reopen_name_locked_table():
        Changed function signature to make it more robust against erroneous usage.
    sql/sql_base.cc:
      reopen_name_locked_table():
        Changed function signature to make it more robust against erroneous usage.
        Obtaining LOCK_open lock is now resposibility of caller.
        When searching for the table to open we should not prefer connection's current
        database over database which was explicitly specified in TABLE_LIST::db member
        (even if database is not explicitly specified for table in original query
        TABLE_LIST::db will be set properly at parsing stage).
        Fixed behavior of function in cases when error occurs during opening of table.
    sql/sql_table.cc:
      prepare_for_restore()/prepare_for_repair():
        We should not prefer connection's current database over database which was
        specified in TABLE_LIST::db member (even if database is not explicitly
        specified for table in original query TABLE_LIST::db will be set properly
        at parsing stage). Fixed behavior in unlikely case when we are unable
        to open table which we are restoring/reparing at the end of preparation
        stage.
    sql/sql_trigger.cc:
      mysql_create_or_drop_trigger():
        Now instead of opening and locking table, creating trigger, and then trying
        to invalidate all instances of this table in table cache, we obtain name
        lock on table first (thus ensuring that no other thread has this table
        open), open it, create trigger and then close table therefore releasing lock.
        New approach is more in line with other places where change .frm files
        (i.e. change table meta-data).
        With this change we also get rid of deadlock which occured in cases when we
        were trying to create two triggers for the same InnoDB table concurrently
        and both threads were able to reach close_cached_table() simultaneously.
        (Alternative was to forbid to InnoDB downgrade locks for CREATE/DROP
         TRIGGER statements in one way or another but I think that proposed
         solution is better long term).
    dd02b98d
sql_trigger.cc 25.9 KB