Общее количество блокировок превышает размер таблицы блокировок. - PullRequest
55 голосов
/ 01 августа 2011

Я запускаю отчет в MySQL. Один из запросов включает вставку большого количества строк во временную таблицу. Когда я пытаюсь запустить его, я получаю эту ошибку:

Код ошибки 1206: количество блокировок превышает размер таблицы блокировок.

Запрашиваемые вопросы:

create temporary table SkusBought(
customerNum int(11),
sku int(11),
typedesc char(25),
key `customerNum` (customerNum)
)ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into skusBought
select t1.* from
    (select customer, sku, typedesc from transactiondatatransit
    where (cat = 150 or cat = 151)
    AND daysfrom07jan1 > 731
group by customer, sku
union
select customer, sku, typedesc from transactiondatadelaware
    where (cat = 150 or cat = 151)
    AND daysfrom07jan1 > 731
group by customer, sku
union
select customer, sku, typedesc from transactiondataprestige
    where (cat = 150 or cat = 151)
    AND daysfrom07jan1 > 731
group by customer, sku) t1
join
(select customernum from topThreetransit group by customernum) t2
on t1.customer = t2.customernum;

Я читал, что изменение файла конфигурации для увеличения размера пула буферов поможет, но это ничего не дает. Как можно исправить это, как временное решение или постоянное исправление?

EDIT: изменена часть запроса. Это не должно повлиять, но я все нашел и заменил и не понял, что это облажалось. Не влияет на вопрос.

РЕДАКТИРОВАТЬ 2: Добавлено typedesc к t1. Я изменил его в запросе, но не здесь.

Ответы [ 9 ]

51 голосов
/ 06 июня 2012

Эта проблема может быть решена путем установки более высоких значений для переменной MySQL innodb_buffer_pool_size.Значение по умолчанию для innodb_buffer_pool_size будет 8,388,608.

Чтобы изменить значение настроек для innodb_buffer_pool_size, см. Приведенный ниже набор.

  1. Найдите файл my.cnf изсервер.Для серверов Linux это будет в основном /etc/my.cnf
  2. Добавить строку innodb_buffer_pool_size=64MB к этому файлу
  3. Перезапустить сервер MySQL

Чтобы перезапустить сервер MySQL, вы можете использовать любой из следующих 2 вариантов:

  1. перезапуск службы mysqld
  2. / etc / init.d / перезапуск mysqld

Ссылка Общее количество блокировок превышает размер таблицы блокировок

21 голосов
/ 15 августа 2011

Я нашел другой способ решить эту проблему - использовать Table Lock. Конечно, это может быть неуместно для вашего приложения - если вам нужно обновить таблицу одновременно.

См: Попробуйте использовать LOCK TABLES для блокировки всей таблицы, вместо действия по умолчанию блокировки на уровне строк InnoDB MVCC. Если я не ошибаюсь, «таблица блокировок» относится к внутренней структуре InnoDB, в которой хранятся строки и идентификаторы версий для реализации MVCC с битом, идентифицирующим строку, которая модифицируется в операторе, и с таблицей из 60 миллионов строк вероятно превышает объем памяти, выделенной для него. Команда LOCK TABLES должна решить эту проблему, установив блокировку на уровне таблицы вместо уровня строки:

SET @@AUTOCOMMIT=0;
LOCK TABLES avgvol WRITE, volume READ;
INSERT INTO avgvol(date,vol)
SELECT date,avg(vol) FROM volume
GROUP BY date;
UNLOCK TABLES;

Jay Pipes, Менеджер по связям с общественностью, Северная Америка, MySQL Inc.

13 голосов
/ 03 августа 2011

Из документации MySQL (которую вы уже прочитали, как я вижу):

1206 (ER_LOCK_TABLE_FULL)

Общее количество блокировок превышает размер таблицы блокировок.Чтобы избежать этой ошибки, увеличьте значение innodb_buffer_pool_size.В рамках отдельного приложения обходным путем может быть разбивка большой операции на более мелкие части. Например, если ошибка возникает для большого INSERT, выполните несколько меньших операций INSERT.

Если увеличение innodb_buffer_pool_size не помогает, просто следуйте указаниямна выделенной жирным шрифтом части и разделите вашу ВСТАВКУ на 3. Пропустите СОЮЗЫ и сделайте 3 ВСТАВКИ, каждая с присоединением к таблице topThreetransit .

2 голосов
/ 06 июля 2017

в Windows: если у вас есть MySQL верстак. Перейти к состоянию сервера. найти расположение запущенного файла сервера в моем случае это было:

C:\ProgramData\MySQL\MySQL Server 5.7

откройте файл my.ini и найдите buffer_pool_size. Установите высокое значение. значение по умолчанию 8M. Вот как я исправил эту проблему

2 голосов
/ 09 сентября 2011

Если вы правильно структурировали свои таблицы так, чтобы каждая из них содержала относительно уникальные значения, то менее интенсивный способ сделать это - сделать 3 отдельных оператора вставки, по 1 для каждой таблицы, с включенным фильтром соединения для каждая вставка -

INSERT INTO SkusBought...

SELECT t1.customer, t1.SKU, t1.TypeDesc
FROM transactiondatatransit AS T1
LEFT OUTER JOIN topThreetransit AS T2
ON t1.customer = t2.customernum
WHERE T2.customernum IS NOT NULL

Повторите это для двух других таблиц - копирование / вставка - хороший метод, просто измените имя таблицы FROM. ** Если вы пытаетесь предотвратить дублирование записей в своей таблице SkusBought, вы можете добавить следующий код соединения в каждый раздел перед предложением WHERE.

LEFT OUTER JOIN SkusBought AS T3
ON  t1.customer = t3.customer
AND t1.sku = t3.sku

, а затем последняя строка предложения WHERE-

AND t3.customer IS NULL

Ваш исходный код использует несколько подзапросов, и оператор UNION может быть дорогостоящим, поскольку он сначала создаст собственную временную таблицу, чтобы заполнить данные из трех отдельных источников, а затем вставить в таблицу, которую вы хотите ДЛИННЫМ при запуске другой подзапрос для фильтрации результатов.

1 голос
/ 30 ноября 2018

Во-первых, вы можете использовать команду sql show global variables like 'innodb_buffer%'; для проверки размера буфера.

Решение - найти ваш my.cnf файл и добавить,

[mysqld]
innodb_buffer_pool_size=1G # depends on your data and machine

НЕ забудьте добавить [mysqld], иначе не получится.

В моем случае Ubuntu 16.04 , my.cnf находится в папке /etc/mysql/.

1 голос
/ 08 мая 2018

Я использую окна MySQL с верстаком MySql.Перейдите в раздел Сервер> Состояние сервера. Вверху написано файл конфигурации: «путь» (C:\ProgramData\MySQL\...\my.ini)

Затем в файле «my.ini» нажмите control + F и найдите buffer_pool_size.Установите значение выше, я бы рекомендовал 64 МБ (по умолчанию 8 МБ).

Перезапустите сервер, перейдя в Экземпляр> Запуск / Завершение работы> Остановить сервер (а затем снова запустить сервер)

В моем случае я не смог удалить записи из моей таблицы.

0 голосов
/ 25 апреля 2019

Этот ответ ниже не дает прямого ответа на вопрос ОП.Тем не менее, я добавляю этот ответ здесь, потому что эта страница является первым результатом, когда вы Google «Общее количество блокировок превышает размер таблицы блокировок».

Если запрос, который вы выполняете, анализируетВо всей таблице, которая охватывает миллионы строк, вы можете попробовать цикл while вместо изменения пределов в конфигурации.

При взгляде в то время как он разобьется на части.Ниже приведен пример зацикливания по индексируемому столбцу DATETIME.

# Drop
DROP TABLE IF EXISTS
new_table;

# Create (we will add keys later)
CREATE TABLE
new_table
(
    num INT(11),
    row_id VARCHAR(255),
    row_value VARCHAR(255),
    row_date DATETIME
);

# Change the delimimter
DELIMITER //

# Create procedure
CREATE PROCEDURE do_repeat(IN current_loop_date DATETIME)
BEGIN

    # Loops WEEK by WEEK until NOW(). Change WEEK to something shorter like DAY if you still get the lock errors like.
    WHILE current_loop_date <= NOW() DO

        # Do something
        INSERT INTO
            user_behavior_search_tagged_keyword_statistics_with_type
            (
                num,
                row_id,
                row_value,
                row_date
            )
        SELECT
            # Do something interesting here
            num,
            row_id,
            row_value,
            row_date
        FROM
            old_table
        WHERE
            row_date >= current_loop_date AND
            row_date < current_loop_date + INTERVAL 1 WEEK;

        # Increment
        SET current_loop_date = current_loop_date + INTERVAL 1 WEEK;

    END WHILE;

END//

# Run
CALL do_repeat('2017-01-01');

# Cleanup
DROP PROCEDURE IF EXISTS do_repeat//

# Change the delimimter back
DELIMITER ;

# Add keys
ALTER TABLE
    new_table
MODIFY COLUMN
    num int(11) NOT NULL,
ADD PRIMARY KEY
    (num),
ADD KEY
    row_id (row_id) USING BTREE,
ADD KEY
    row_date (row_date) USING BTREE;

Вы также можете адаптировать его к циклу по столбцу «num», если ваша таблица не использует дату.

Надеюсь, это кому-нибудь поможет!

0 голосов
/ 26 января 2018

Стоит сказать, что цифра, используемая для этого параметра, указана в БАЙТАХ - выяснил это нелегко!

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