0

tree_elements という名前のテーブルから仮想パス名を作成する関数が 2 つあります。関数 path(id,language) は、テーブルの更新時に呼び出されます。テーブルの更新によってデッドロックが発生し、エラー メッセージが表示されることがあります (例)。

select path(621163,"de") 
Deadlock found when trying to get lock; try restarting transaction

ロックがかかる理由がわかりません。関数は選択のみを使用し、更新、挿入、削除は使用しません。どうすればこの現象を回避できますか?

私の機能があります:

mysql> show create function path\G
*************************** 1. row ***************************
            Function: path
            sql_mode:
     Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `path`(id integer, language char(2)) RETURNS varchar(255) CHARSET utf8
    READS SQL DATA
    DETERMINISTIC
    COMMENT 'Converts a record id into an url string with path'
begin
        declare ret varchar(255);
        declare r varchar(255);
  declare element varchar(255);
        set ret = path_component(id,language);
        set id = (select id_parent from tree_elements t where t.id=id);
        while (id > 0) do
    set element = concat(path_component(id,language), '/');
    if (locate( element, ret )) then return concat( 'Infinite loop in path for id ', id ); end if;
                set ret = concat(path_component(id,language), '/', ret );
                set id = (select id_parent from tree_elements t where t.id=id);
        end while;
        return ret;
end
character_set_client: latin1
collation_connection: latin1_swedish_ci
  Database Collation: utf8_general_ci

mysql> show create function path_component\G
*************************** 1. row ***************************
            Function: path_component
            sql_mode:
     Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `path_component`( id integer, language char(2)) RETURNS varchar(500) CHARSET utf8
    READS SQL DATA
    DETERMINISTIC
begin
   declare f varchar(255);
        set f = (select case language
                when 'en' then title_en
                when 'de' then title_de
                else title_en
                end
        from tree_elements t where t.id=id);
        if (isnull(f) or length(trim(f)) = 0) then
                set f = (select title_en from tree_elements t where t.id=id);
        end if;
        return url(f);
end
character_set_client: latin1
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
4

1 に答える 1

0

テーブル (またはテーブルのページ) をロックするためにデータを挿入または更新する必要はありません。データを選択すると、(RDBMS エンジンのデフォルトのロック ポリシーに従って) テーブルがロックされる可能性があります。そのため、データの選択中にテーブルをロックしないようにエンジンに指示する特定のディレクティブがあります。(SQL Server では、タルベの名前の後の NoLock ディレクティブ)。テーブルで複数の行を選択すると、テーブルが複数のページでロックされる可能性があります。同じテーブルに対して 2 つの異なるクエリを実行し、クエリ 1 がクエリ 2 が必要とするページをロックし、クエリ 2 がクエリ 1 が必要とするページをロックすると、デッドロックが発生します。ページが特定の順序でロックされることを保証します。通常、デッドロック状態は対処が最も難しい問題です。

于 2012-02-19T12:41:33.447 に答える