2012-02-19 7 views
0

私は、tree_elementsという名前のテーブルから仮想パス名を作成する2つの関数を持っています。関数パス(id、language)は、テーブルの更新時に呼び出されます。場合によっては、テーブルの更新により、エラーメッセージ(例)のデッドロックが発生します。selectクエリだけでmysql関数のデッドロックを回避する方法はありますか?

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

なぜロックされているのかわかりません。この関数は、select、no update、insertなし、deleteを使用しません。どうすればこの現象を回避できますか?あなたは、テーブルをロックするためにデータを挿入または更新する必要はありません

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 
+0

使用可能な回答[here](http://stackoverflow.com/questions/917640/any-way-to-select-without-causing-locking-in-mysql)があります。 – Bojangles

答えて

0

(またはテーブルのページ):

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

+0

ありがとうございます。その間、私はSETセッションのTRANSACTION ISOLATION LEVEL READ UNCOMMITTEDを使って自分の関数内でSELECTをブラケット化しました。 SETセッション・トランザクション・アイソレーションLEVEL REPEATABLE READ;それぞれ、今までは新しいエラーメッセージはありません。 –

関連する問題