|
 1.3 Кб |
|
| Доброе время суток!
Имею следующую проблему: есть две базы данных. В базу №1 (base1), сыпится поток netflow. Есть необходимость, чтобы триггер брал данные перед вставкой и кидал в базу №2 (base2). Но не просто втупую перекидывал, а сравнивал текущие данные, т.е. если запись с приходящим айпишником уже есть, то делал UPDATE записи добавляя сумму трафика, если принимаемого айпишника нет, то делал бы INSERT.
Я примерно догадываюсь, что делается через цикл внутри тригера, но как это реализовать не знаю... перепробовал уже кучу вариантов и доков перелистал... но что-то не выходит.
Примерный дамп обеих баз в прикрепленном файле | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 09:32)
| | По-моему, INSERT ... ON DUPLICATE KEY UPDATE - в самый раз.
И никаких циклов. | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 09:48)
| | а можно немного поподробнее? Я до этого вообще никогда с триггерами не работал, а тут как оказалось ну очень нада.... | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 09:50)
| | так а этот запрос напрямую с триггерами не связан.
Вы уж определитесь, что вас интересует - триггеры или логика заполнения БД. | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 10:13)
| | наверное нужна связь двух баз в режиме master-master | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 10:19)
| | да тут какбы вопрос по заполнению базы, но в base2 он не просто должен ложить, но еще и суммировать, что-то типа in=in+NEW.in, out=out+NEW.out, для уже существующих данных ipin и ipout | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 10:23)
| | т.е. информация в базах с одним и тем же id разная? | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 10:28)
| | ну как бы id там нет. Принцып такой: делаю свою систему биллинга. Данные баз предназначены для сбора статистики. В базу base1 валится поток Netflow, т.е. каждые там 1-2 секунды в таблицу попадает строка в которой содержаться айпи пользователя, айпиприемника, порты, сумма входящего и иисходящего трафика. А триггер должен брать эту строчку и вставлять ее в таблицу базы base2, узнавая есть ли там айпишник пользователя и приемника или нет их и соответственно вставлять новые данные или обнавлять существующие. | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 10:23)
| | Между прочим, у Вас две базы или всё же две таблицы в одной базе? | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 10:37)
| | Две разные базы | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 10:38)
| | На одном сервере или на разных? | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 10:38)
| | пока в тестовом режиме, на одном сервере, как все пойдет нормально, на разные сервера | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 10:47)
| | триггер не будет работать с базами, находящимися на другом сервере. | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 10:19)
| | Это еще что за зверь зачем? | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 10:37)
| | в целях распределения ресурсов по 2-3 машинам... при большом объеме пользователей данные будут сыпаться с ужасными масштабами, вплоть до 500 гигов за месяц и это не предел... да и начальство так захотело... | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 10:41)
| | посмотрите тему http://softtime.ru/forum/read.php?id_forum=3&id_theme=66427
хотя там речь идёт о двух таблицах одной базы, но принцип, по-моему, тот который вас интересует (ближе к концу дискуссии) там и вложение есть для примера. | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 09:32)
| | пытаюсь сделать вот такой тригер:
CREATE TRIGGER `sts_base1`.`addbase2` AFTER INSERT ON `sts_base1`.`raw20090821`
FOR EACH ROW
BEGIN
INSERT INTO `sts_base2.stat200908` (`ipin`, `ipout`, `potrin`, `portout`, `in`, `out`)
VALUES (`NEW.ipin`, `NEW.ipout`, `NEW.potrin`, `NEW.portout`, `NEW.in`, `NEW.out`)
ON DUPLICATE KEY UPDATE
`ipin` = VALUES(`NEW.ipin`),
`ipout` = VALUES(`NEW.ipin`);
END
|
выдает вот такую ошибку при вставке:
mysql> insert into raw20090821 values ('3', '2', '3', '4', '5', '6');
ERROR 1146 (42S02): Table 'sts_base1.sts_base2.stat200908' doesn't exist
Это понятно что он не может найти таблицу 'sts_base1.sts_base2.stat200908' , но есть таблица 'sts_base2.stat200908' ... откуда он такое берет? | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 11:25)
| | Вам же сказали, что триггер не будет работать с другим сервером, тогда к чему убивать время на то что в последствии окажется ненужным. | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 11:30)
| | Бог с ними с серверами... как хотяб на одном сделать... | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 11:34)
| | я вам ссылку дал, смотрели?
и ещё в последнем номере журнала ][акер меня заинтересовала статья "Да пошел ты, SQL" | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 11:25)
| | Может быть всё же `sts_base2`.`stat200908` а не `sts_base2.stat200908` ?
Не факт, правда, что поспособствует, но так как сейчас - явная лажа. | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 11:50)
| | не спасла меня ссылка, но исправление на `sts_base2`.`stat200908` выдало новую ошибку, о том, что `sts_base2.stat200908` doesn't exist | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 13:14)
| | Да что вы так привязались к этим триггерам
Вы же сказали что база будет и так сильно нагружена, а если ещё после каждого инсёрта триггер юзать вам сервак в криогенную камеру останется засунуть. В чём выгода? С тем же успехом можно сразу писать в базу2. (даже КПД выше будет в этом случае)
В моём варианте база в которую сплошным потоком пишется информация используется в качестве буфера, объём этого "буфера" можно подобрать уже во время работы, т.е. выбрать золотую середину.
И весь смысл затеи в том что этот буфер будет периодически очищатся (!)
У вас же база1 будет неимоверно разрастаться от секунды к секунде.
В общем делайте как хотите, я вам не указ. (да и морального права не имею) | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 14:46)
| | >Да что вы так привязались к этим триггерам
>Вы же сказали что база будет и так сильно нагружена, а если ещё после каждого инсёрта триггер юзать вам сервак в криогенную камеру останется засунуть. В чём выгода? С тем же успехом можно сразу писать в базу2.
не надо так шипеть.
Я вполне могу предположить, что внешний источник данных просто не умеет делать INSERTы дважды. | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 15:11)
| | а я вовсе и не шипеть, наоборот я уже давно превратился в одно большое ухо... и пока что слушаю тишину.
Я вполне могу предположить, что внешний источник данных просто не умеет делать INSERTы дважды.
Если можно скажите в двух словах суть, и как от этого спасает применение базы1.
Пока что я вижу 1 инсёрт и 1 триггер к нему в связке. | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 15:15)
| | суть такая, что в базу1 будет валиться неотсартированный поток, т.е. все содержание netflow. валиться будет кучно. В последующем обрабатывать такие данные будет крайне долго... для этого данные валятся в базу2 и сортируются по признаку ip, т.е. если совпадает ip-источника и ip-приемникаданные переписываюся. а информация в базе1 раз в 2-3 месяца пакуется и удаляется в архив на 3 года...
> Я вполне могу предположить, что внешний источник данных просто не умеет делать INSERTы дважды.
Именно так и было... я работаю над sql и php частью, в оборудование не лезу, если мне сказали что не может 2 INSERT делать, то и вопросов я больше не задавал... Поток снимается Netflo версии 5, а для него якобы нет каких-то премудростей. Ну да и ладна.
Сложив силы, написал вот такой тригер:
CREATE TRIGGER `sts_base1`.add BEFORE INSERT
ON raw20090821
FOR EACH ROW
begin
INSERT INTO `sts_base2`.`stat200908` VALUES (NEW.`ipin`, NEW.`ipout`, NEW.`portin`, NEW.`portout`, NEW.`in`, NEW.`out`)
end
|
Он работает хорошо.
Не имея в базе PRIMARY KEY вариант с ON DUPLICATE KEY UPDATE отпадает (а жаль). Далее необходимо сделать проверочку. Если совпадают поля ipin и ipout в базе2, то необходимо сделать UPDATE этой строки в базе2, если не савпадают, то INSERT новой строки.
На самом деле, кроме триггеров, для меня сейчас нет доступных вариантов реализации... если есть другое видение картины, будь-те добры, подскажите... | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 16:00)
| | Стоп. А что мешает поставить primary key на `sts_base2`.`stat200908`.(`ipin`,`ipout`) ? | |
|
|
|
|
|
|
|
для: Trianon
(25.08.2009 в 16:04)
| | ipin и ipout не могут быть примари, т.к. ... просто пример: пошел пользователь с ip 192.168.2.2 на ip 10.40.40.2, потом пошел на ip 10.40.40.5, потом на ip 10.40.40.28, ipin остается неменяемым, а ipout меняется | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 16:09)
| | ipin остается неменяемым, а ipout меняется
но как одно целое, то они уникальны?
Трианон, если не ошибаюсь, говорил о первичном ключе на оба поля. | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 16:09)
| | я не предлагал делать праймэри один из них.
Можно сделать составной первичный ключ.
Соответственно, ключом будет 192.168.2.2 - 10.40.40.2 | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 16:00)
| | если мне сказали что не может 2 INSERT делать, то и вопросов я больше не задавал...
а я вот задаю и хочу разобраться в этом.
2 INSERT - речь я так понимаю идёт о инсёрте в одну базу и невозможности повторить этот инсёрт во вторую базу, так?
Я всего лишь пристебался к вашему триггеру только лишь потому что он срабатывает по инсёрту, если бы речь шла о зеркале базы, то никаких вопросов, но это не ваш случай.
Если бы вы стартовали триггер по другому условию (например каждые 1000 инсёртов), то я бы тоже почти не задавал вопросов.
Давайте на пальцах (в лучшем смысле этого слова) поговорим.
в базу 1 летят данные (неважно откуда), назовём их "пакет1"
теперь скажите что делает ваш триггер?
пока, что я вижу, что он кидает этот "пакет1" в базу2 | |
|
|
|
|
|
|
|
для: dimm_kz
(25.08.2009 в 16:00)
| | Важно ли для программиста образное мышление?
Может у меня слишком бурная фантазия, но вот что я вижу в вашем варианте.
Имеются две цистерны, назовём их база1 и база2.
В базу 1 капает эмульсия (например вода с песком), предположим объёмом в одну чайную ложку.
Василий Петрович Триггер наблюдая за процессом попадания эмульсии в цистерну номер один, хватает ложку
наливает туда воды, засыпает песка и доводит это дело до состояния эмульсии (грубо говоря создаёт копию).
Затем бежит к цистерне номер два (база2), у которой на входе стоит сепаратор, кидает туда ложку скопированной
эмульсии и нажимает на кнопку. Затем рвёт когти обратно к цистерне номер один.
В итоге через месяц база1 содержит пару тонн говна эмульсии, в базе2 чистая как слеза вода.
Теперь о моём варианте
(продолжение следует)
___
лирическое отступление о шипении
"Вам может показаться, что мы квакаем, на самом деле песню мы поём" | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 17:21)
| | Имеем те же самые две цистерны (база1 и база2)
В цистерну номер один капает ложка эмульсии, вторая, третья.. стопятьдесятвторая... и тд.
В это время Иван Михалыч Крон сидит курит, да поглядывает на часы
Звенит будильник и дядя Ваня, нажимает на кнопку базы1 и песок выпадает в осадок, затем выбрасывает песок,
сливает чистую воду в ведро и несёт в цистерну номер два.
В итоге через месяц(а также после каждой ходки дяди Вани) имеем чистую базу1 и базу2 содержащую чистую
как слеза воду (в принципе, там может и спирт оказаться)
А теперь наша задача как заварившего всю эту байду, добиться того чтобы Иван Михалыч Крон
не шастал туда сюда с полуппорожним ведром или не надорвался половиной цистены. | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 17:36)
| | База1 и база 2 сейчас идентичны, да. Но это только пока я учусь, на самом деле у нетфло очень много полей, а из них мне много не надо | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 17:36)
| | Ребят, спасибо за дискусии, завтра продолжем, сегодня хэд уже не тот! Спасибо еще раз! | |
|
|
|
|
|
|
|
для: Valick
(25.08.2009 в 17:36)
| | Гаспада! ну просто огромное вам спасибо! на свежую голову и с вчерашней влитой информацией все пришло само!!! Возможно тригеры не самый лучший вариант реализации, но сейчас он работает и это главное! возможнов дальнейшем всем этим безобразием и будет рулить Иван Михалыч Крон, но пока так))))))))
Для тех кому интересна реализация вот:
CREATE DEFINER=`root`@`localhost` TRIGGER `base1`.add BEFORE INSERT
ON raw20090821
FOR EACH ROW
begin
INSERT INTO `base2`.`stat200908` VALUES (NEW.`ipin`, NEW.`ipout`, NEW.`portin`, NEW.`portout`, NEW.`in`, NEW.`out`)
ON DUPLICATE KEY UPDATE
`in` = NEW.`in` + `in`,
`out` = NEW.`out` + `out`;
end
|
Это при реализации составного первичного ключа полей ipin и ipout | |
|
|
|
|
|
|
|
для: dimm_kz
(26.08.2009 в 09:27)
| | К сожалению, как показала практика, при активном поступлении данных в базу, имея 2 тригера на обработку, MySQL падает... сэляви... | |
|
|
|