Mysql тупиковое объяснение - PullRequest
       1

Mysql тупиковое объяснение

1 голос
/ 31 октября 2011

Мне нужна помощь в разрешении тупиковой ситуации, с которой я сталкиваюсь.

Ниже приведен тестовый скрипт, имитирующий возникшую у меня проблему, у меня есть таблица тегов, которую по запросу можно вставить / обновитьмного записей, все в одной транзакции.

Я знаю, что тупик возникает из-за того, что множество потоков блокируют одни и те же записи, и я хотел бы получить отзыв о том, как их можно избежать

Я бегу ab -n 100 -c 5 http://localhost/script.php

Это таблица

CREATE TABLE `tags` 
(
  `id` INT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(40) COLLATE utf8_unicode_ci DEFAULT NULL,
  `weight` INT(8) DEFAULT NULL,
  `type` ENUM('1','2','3') COLLATE utf8_unicode_ci DEFAULT NULL,
  `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `tag_name` (`name`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

<?php
function go() {

    $db = DB::getInstance();
    $db->start_transaction();
    $tgs = array('electricity', 'emergency', 'trees', 'New Jersey', 'Canada funnelled');
    foreach($tgs as $tg) {
        $arr_tags = array(
            'name' => $tg,
            'weight' => '0',
            'type' => TagTable::PRIMARY
        );
        $tag_instance = new Tag($arr_tags);
        $tag_instance->save(true);
        // the save method executes a query like the below
        // INSERT INTO tags (weight, type, modified, id, name) VALUES(0, "1", NULL, NULL, "$tag") ON DUPLICATE KEY UPDATE weight = weight+1;

    }
    $db->commit();
}
go();
?>

1 Ответ

2 голосов
/ 31 октября 2011

Удивительно, но даже с InnoDB могут возникать тупики. Причина этого?

Кластерный индекс (известный внутри как gen_clust_index) может периодически блокироваться в середине транзакции с использованием групповых вставок. Что интересно в INSERT в транзакциях, во многом связано с файлами журналов InnoDB. Предыдущее состояние строки данных, которую вы ВСТАВЛЯЕТЕ, является одним из несуществующих строк. Такие MVCC данные, представляющие несуществующую строку, будут записаны в журналах повторов для поддержки откатов, грязного чтения и тому подобного. Выполнение групповых вставок создаст множество этих несуществующих строк для отката.

Однажды я прочитал серию вопросов от одного сотрудника DBA StackExchange о тупиковых ситуациях с последовательными обновлениями. Вот эти вопросы и мои ответы:

Возможно, вам придется попробовать выполнить массовые INSERT без транзакции с одним из следующих:

  • с коммитом после каждой вставки
  • использовать AUTOCOMMIT = 1

Если в транзакции должны быть вставки, попробуйте увеличить размер файлов журнала InnoDB и буфера массовой вставки :

Шаг 01) Добавьте эту строку в /etc/my.cnf

[mysqld]
bulk_insert_buffer_size=256M
innodb_log_file_size=2047M

Шаг 02) service mysql stop

Шаг 03) rm -f /var/lib/mysql/ib_logfile[01]

Шаг 04) service mysql start

Во время запуска mysql воссоздаются ib_logfile0 и ib_logfile1

Попробуйте! Надеюсь, это поможет.

ОБНОВЛЕНИЕ 2011-10-31 12:43 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Я только что ответил на такой вопрос в DBA StackExchange 3 дня назад

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...