Table 'table_name' doesn't exist.

Jarhead

Постоялец
Регистрация
17 Июн 2011
Сообщения
414
Реакции
169
При обновлении интернет магазина, создается временная таблица, после занесения данных в которую, выполняется хранимая процедура:

Код:
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `sync_fl`()
BEGIN
  # READ ROWS COUNT IN ALL NEW TABLES AND SHOW ERROR IF ONE IS EMPTY
  DROP TABLE IF EXISTS `sh_prod_im__`;
  ALTER TABLE `sh_prod_im` RENAME TO `sh_prod_im__`;
  ALTER TABLE `sh_prod_im_` RENAME TO `sh_prod_im`;
END$$
DELIMITER ;

Интернет-магазин имеет много посещений в день и видать кто то ловит момент переименования таблицы и возникает ошибка, как можно оптимизировать данный процесс чтобы подобных проблем не возникало? Читал что процесс изменения названия таблицы занимает 0.10 sec и это не подходит.
 
Оберни в транзакцию.
Попробуй избавится от хранимки.
Возможно результат есть смысл кешировать и шарить для разных пользователей.
 
а зачем писать в темп-таблицу а потом переименовывать ? что за данные в таблице, обновлять не получиться сразу в ней ?
 
а зачем писать в темп-таблицу а потом переименовывать ? что за данные в таблице, обновлять не получиться сразу в ней ?

Есть таблица, с информацией о фотографиях товаров, фотографии товаров переодически/часто могут меняться, кол-во фотографий в большую или меньшую сторону, их очередность или ID фотографий. Обновление происходит по требованию или раз в час. Данные приходят о всех товарах целиком, нужно обновлять данные эти так, чтобы клиенты интернет-магазина не испытывали неудобств, не попадали на блокировку записей/смену записей, вообщем для клиентов обновление должно быть полностью незаметным, т.е. моментальным. Insert в рабочую таблицу без транзакции, откуда происходит селект, категорически не возможен. Данные все должны обновится одновременно и моментально. Вопрос как это сделать?

Пока в черновике записан вот такой вариант, но я не до конца думаю что он удачный:

У меня уже есть таблица с данными о товарах, откуда берется инфа на сайт:

Код:
CREATE TABLE `test` (
  `prod` int(10) unsigned NOT NULL,
  `type` int(10) unsigned NOT NULL,
  `pict` int(10) unsigned NOT NULL,
  `updated` int(1) unsigned DEFAULT '1',
  PRIMARY KEY (`prod`,`type`,`pict`)
) ENGINE=InnoDB;

Далее я обновляю эту таблицу со склада:

Код:
DROP TEMPORARY TABLE IF EXISTS `test123`;

CREATE TEMPORARY TABLE `test123` (
    `prod` int(10) unsigned NOT NULL,
        `type` int(10) unsigned NOT NULL,
        `pict` int(10) unsigned NOT NULL,
        PRIMARY KEY (`prod`,`type`,`pict`)
        ) ENGINE = MEMORY;

insert into `test123` values (1,1,1),(2,2,2);

Далее я запускаю хранимую процедуру с транзакцией:

Код:
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `sync_fl2`()
BEGIN

DECLARE exit handler for sqlexception
  BEGIN
    -- ERROR
  ROLLBACK;
END;

DECLARE exit handler for sqlwarning
BEGIN
    -- WARNING
ROLLBACK;
END;

START TRANSACTION;

  UPDATE `test` SET `updated` = 0;

  INSERT INTO `test` (`prod`,`type`,`pict`)
    SELECT `prod`,`type`,`pict`
    FROM `test123`
    ON DUPLICATE KEY UPDATE `updated` = 1;

  DELETE FROM `test` WHERE `updated` = 0;

COMMIT;
END$$
DELIMITER ;

Код:
DROP TEMPORARY TABLE IF EXISTS `test123`;

Смущает что чисто теоритически если во время обновления из памяти произойдет сбой то данные обновятся частично и это можно будет отловить только визуально и нужно будет работать с фиксом максимального размера таблицы в памяти.
 
Последнее редактирование:
ой и на городили! какой еще сбой в памяти :) работая с транзакций, при правильном построение процедуры вам гарантирован откат до начального состояния (до момента измения) таблицы. Это раз. Когда обновляете данные в таблице с транзакцией, пока транзакция не завершена, пользователю отдаются данные на момент до начала изменения. Тоесть он и не видет что идет обновление, я потом бац, обновляет страницу, а данные уже другие > транзакция закоммителась. То, что Вы делаете в временной таблицей / insert, переимменовыванием, все муторно и до боли не правильно. Мое профессиональное мнение.
 
ой и на городили! какой еще сбой в памяти :) работая с транзакций, при правильном построение процедуры вам гарантирован откат до начального состояния (до момента измения) таблицы. Это раз. Когда обновляете данные в таблице с транзакцией, пока транзакция не завершена, пользователю отдаются данные на момент до начала изменения. Тоесть он и не видет что идет обновление, я потом бац, обновляет страницу, а данные уже другие > транзакция закоммителась. То, что Вы делаете в временной таблицей / insert, переимменовыванием, все муторно и до боли не правильно. Мое профессиональное мнение.

Это черновик, пока создается просто таблица обычная, заполняется, а потом из нее уже транзакцией заполняется другая, а как бы Вы сделали если приходили бы данные в массиве и нужно было бы удалять и после заполнять существующую таблицу из которой делается селект на сайт?
 
Есть таблица, это ваша основа. Делайте в нее вставку, обновление, удаление.

Начну с конца, самое противное это удаление сотни, тысячи на наконец миллионов записей (которые больше не нужны) не блокируя таблицу, делается это частями, причем логика вывода данных из таблиц во фронтенд должна основываться на каком нибудь флаге. Тоесть SELECT * FROM xxx WHERE Deleted = 0. Тоесть все что Deleted = 1 пользоваться так и так не увидет, а вы сможете частями, когда захотите, например ночью, когда активность под 0% подчищать таблицу: DELETE xxx WHERE Deleted = 1 LIMIT x, делается в цикле пока есть что удалять. Кроме того, в любой таблице всегда (просто примите это за правило) должно быть поле даты вставки/обновления записи), можно разделить на два поля, можно оставить в одном: TIMESTAMP, его писать во время Insert или Update: NOW()

Остаеться добавить (INSERT) и обновить(UPDATE), при чем не только записи но и сам Флаг Deleted = 1 у тех записей, которые больше не нужны.
Есть несколько способов, нужно выбрать из условий, количество записей, частоты обновления, в конце концов версии SQL (MySQL),
но то что я от вас уловила, сделала бы так:

1. Найти максимальную дату обновление: SELECT MAX(Timestamp) FROM xxx, сохранить значение это в переменную
2. При помощи INSERT INTO + ON DUPLICATE KEY UPDATE вставить новые записи и обновить существующие (на основе Primary Keys).
3. Обновить флаг Deleted у всех записей у которых TIMESTAMP оказался старее вашей переменной из пункта 1: DELETE FROM xxx WHERE Timestamp < @Timestamp.
Посколько значение не обновилось, значит и обновления больше не пришло, тоесть можно удалить. Все зависит конечто от Бизнес-Логики.
4. Ночью подчистить таблицу, как указано выше.

Все пункты (первый можно вынести) выполняются конечно в транзакции.
Все, вроде ничего сложного ...
 
Назад
Сверху