Транзакция MySQL с одним оператором обновления занимает> 4 с в таблице 4000 строк - PullRequest
3 голосов
/ 19 декабря 2011

Большую часть времени эта транзакция занимает <1 с, в среднем 200 мс или около того.Но иногда это занимает> 4 с!Этот sproc запускается 5-6 раз в секунду или около того.

Мой 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 вызывается 5 раз в 1 секунду, и эти транзакции занимают <100 мс.И для четвертых, это не так много одновременных транзакций </p>

  2. Индекс правильно установлен на id

  3. Таблица маленькая ... 4000 строкили около того.

  4. Невозможно запустить медленный журнал запросов, так как это MySQL 5.0, не нужно перезагружать сервер, чтобы включить флаг медленных запросов, если это не последнее средство.

Мне нужны некоторые предложения по поводу причины или того, что еще нужно расследовать.

1 Ответ

1 голос
/ 19 декабря 2011

Не уверен, поможет ли это, но эти строки:

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;

можно переписать как:

    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) также должен помочь оператору UPDATE избежать чтения из таблицы при closed <> 0.

...