2011-12-18 4 views
3

このトランザクションでは、ほとんどの場合、<が1秒かかります。平均は200ms程度です。しかし、たまには4秒以上かかります!このsprocは毎秒5〜6回実行されます。1つの更新ステートメントを使用するMySQLトランザクションは、4000行テーブルの> 4秒を要します

私SPROCは(InnoDBの - REPEATABLE READ)非常に単純です:

START TRANSACTION; 
SELECT end_time INTO currentEndTime FROM auctions WHERE id=var_auction_id; 

IF (ADDTIME(currentEndTime , var_time_increment) < NOW()) THEN 
    UPDATE auctions SET end_time = ADDTIME(NOW(), var_time_increment), price = price+var_price_increment, leader_id = var_leader_id, modified = NOW() WHERE id = var_auction_id AND closed = 0; 
ELSE 
    UPDATE auctions SET end_time = ADDTIME(end_time, var_time_increment), price = price+var_price_increment, leader_id = var_leader_id, modified = NOW() WHERE id = var_auction_id AND closed = 0; 
END IF; 
SELECT ROW_COUNT() INTO myRowCount; 

IF (_error) THEN 
    ROLLBACK; 
ELSE 
    SET var_return = myRowCount; 
    COMMIT; 
END IF; 

私は4Sスパイク、私がしようとした事を引き起こしているかを把握したい:

  1. 私はそれがかもしれないと思いました私はこのsprocが1秒で5回呼ばれているのを見てきましたが、そのトランザクションは< 100msです。そして、4Sのもののために、それは、多くの同時トランザクション

  2. インデックス

  3. 表が小さいIDに適切に設定されている... 4000行ほどではありません。

  4. MySQL 5.0以降の低速クエリログを実際に実行することはできません。最後の手段でない限り、低速クエリフラグをオンにするためにサーバーを再起動しないようにしてください。

私は原因やその他の調査が必要です。

+0

このクエリを実行するサーバーに重い負荷がかかりますか? 'uptime'や' top'コマンドは何を表示しますか?またはタスクマネージャー? (OSによって異なります) –

+0

これはトップ情報です:トップロード平均:0.97,0.89,0.91 タスク:201合計、3実行中、198スリープ状態、0停止中、0ゾンビ CPU:21.7%us、 1.5%sy、0.0%ni、76.4%id、0.0%wa、0.2%hi、0.2%si、0.0%st – Kyra

+0

このボックスは8GのRAMを搭載したクアッドコアAMD Opteron 1354です – Kyra

答えて

1

わからない、これは役立ちますが、これらの行があれば:

UPDATE auctions 
    SET end_time 
     = ADDTIME(CASE WHEN ADDTIME(end_time, var_time_increment) < NOW() 
         THEN NOW() 
         ELSE end_time 
        END 
       , var_time_increment 
       ) 
     , price = price + var_price_increment 
     , leader_id = var_leader_id 
     , modified = NOW() 
    WHERE id = var_auction_id 
     AND closed = 0; 

か::

UPDATE auctions 
    SET end_time 
     = ADDTIME(CASE WHEN end_time < ADDTIME(NOW(), - var_time_increment) 
         THEN NOW() 
         ELSE end_time 
        END 
       , var_time_increment 
       ) 
     , price = price + var_price_increment 
     , leader_id = var_leader_id 
     , modified = NOW() 
    WHERE id = var_auction_id 
     AND closed = 0; 

(closed, id)上の複合インデックス

SELECT end_time INTO currentEndTime FROM auctions WHERE id = var_auction_id; 

IF (ADDTIME(currentEndTime, var_time_increment) < NOW()) THEN 
    UPDATE auctions 
    SET end_time = ADDTIME(NOW(), var_time_increment) 
     , price = price + var_price_increment 
     , leader_id = var_leader_id 
     , modified = NOW() 
    WHERE id = var_auction_id 
    AND closed = 0; 
ELSE 
    UPDATE auctions 
    SET end_time = ADDTIME(end_time, var_time_increment) 
     , price = price+var_price_increment 
     , leader_id = var_leader_id 
     , modified = NOW() 
    WHERE id = var_auction_id 
     AND closed = 0; 
END IF; 

はのように書き換えることができますまた、 UPDATEclosed <> 0の場合、テーブルからの読み取りを避けるためのステートメント。

+0

'id'が主キーであれば、複合インデックスは役に立たないでしょう。主キーでない場合は、表を再設計する必要があります。 –

+0

@TheScrumMeister:なぜ(idがPKの場合)助けにならないのですか?条件 'id = var_auction_id AND closed = 0'は、複合インデックスがない場合にクエリがテーブルを読み込まなければならないことを意味する。 –

+0

実際にはidが主キーです。私は(selectを使って)更新ステートメントの説明を走らせ、それはインデックスから読んでいるようです。 – Kyra

関連する問題