crower: (Crower)
[personal profile] crower
Что лучше? Я тоже думал, что REPLACE проще, пока не понадобилось задействовать тригер.

Предыстория: есть техпроцесс обработки нарядов. Получаем наряд — в базу помещаем запись с десятком параметров (f10s). Выполняем его — появляется ещё пол-десятка параметров (f5s). Можно хранить их в одной таблице, а можно в разных. Во втором случае потребуется дополнительная линковка, накладные расходы. Поэтому, проектируя эту базу много лет назад, оставил всё в одной таблице. Впрочем, у её предшественницы тоже был такой принцип. Но появились новые задачи и переосмысливалось всё, что оставить как есть, что изменить, а от чего отказаться. Ну, это уже не важно… :)

И вот пришло время очередной модернизации. Чтобы всё продолжало работать делаем новую базу на другом сервере: комп поновее, значительно мощнее, операционка с софтом значительно перспективнее. Опять анализировал вопрос f15s или f10s+f5s. Вкусная идея намекала на то, что может быть лучше второй вариант. Бывает ситуации, когда наряд выполнить нельзя. Временно. Тогда в f5s записываем обстоятельства. Назовём этот набор полей статусом наряда. Потом изменяются условия и наряд можно выполнить (становится выполнябельным). Для этого эти поля сбрасываются и робот прописывает туда новые значения. Раньше о необходимости хронологии даже не задумывались и поэтому это было нормально. А тут возникли мысли, что иногда было бы очень не дурно в таких ситуациях видеть весь процесс. Ну, как минимум, иногда приходилось эту хронологию вытаскивать по логам. Среди всех вариантов как это реализовать в конце концов остановился на f15s+f5s.
То есть, в случае довыполнения наряда старый статус переносим в таблицу хронологии, а в основной таблице остаётся всегда актуальный статус. Это позволяет не городить для основной массы записей линковку и основные процессы работают по значительно более простому алгоритму.
Новая база давно создана. Все записи туда скопированы и появляющиеся новые тоже копируются. Специальному трансферовому скрипту с такой схемой работать даже проще: что вынул из старой базы, то затолкал в новую. Чтобы меньше заморачиваться копирую наряды уже со статусом. Механизм не универсальный, простой, удобный и пока работает: последняя скопированная запись определяет «ватерлинию» в базе. Появились новые записи — оказываются выше её. Трансферовый скрипт их копирует и перемещает ватерлинию в новую позицию.
С довыполняемыми нарядами первое время заморачивался и вручную всё делал. Потом озадачился автоматизацией. Но переносить старый статус скриптом с удалённого хоста как-то не очень красиво.
И тут приходит мысль переложить эту задачу на базу.
Можно stored procedure использовать, но я не люблю слишком усложнять конструкцию. К тому же с одной стороны такие финты, конечно, позволяют абстрагироваться от конкретной реализации, но с другой процесс модификации на порядок усложняется. Вот в старой системе у меня есть такая конструкция. Чтобы что-то изменить приходиться пользоваться принципом ханойской башни.
В общем Окам советует: «Нафиг».
И тут приходит мысль заюзать тригер. Хорошоая идея.
При вставке запись сохраняется как есть, а при апдейте старые f5s или состава f15s копируются в отдельную таблицу f5s и тогда старые апдейтятся.
Сказано — сделано.
А не работает.
Минут двадцать убил пока не разобрался что к чему.
Трансферный робот применяет REPLACE. На тот случай, если неправильное или устаревшее значение нужно исправить. Про ON DUPLICATE не помню видел ли. Может видел, но подумал что нафиг нужно усложнять — там же нужно будет ещё раз нужные параметры перечислять. А REPLACE — хлоп! и готово.
Но REPLACE не работает как UPDATE. Он работает как DELETE+INSERT.
Поэтому и тригер на UPDATE при REPLACE не срабатывает.
Тригер на INSERT ничего не знает про OLD-значения, на DELETE ничего не знает про NEW, а тригера на REPLACE в природе (mysql 5.5) не существует.
Облом. Думаем дальше. Одной извилиной подумываю как скриптом всё-таки манипулировать статусом удалённо, но попроще (ака понадёжнее).
И тут, читая мануал приходит мысль: учим трансферового робота делать INSERT…ON DUPLICATE KEY UPDATE, а на таблице (f15s) делаем тригер на UPDATE, который проверяет что (1) старое значение не пустое (незачем копировать пустышку, если такое случиться), и (2) строе и новое значения различаются (чтобы не дублировать статусы. если понадобится переписать основную запись).
Сказано — сделано.
Работает!

Вот а казалось бы REPLACE проще (визуально), а технически — сложнее (DELETE + INSERT). Нет, я конечно, читал про реализацию, но запамятовал, поскольку тогда придумать не мог какая разница.

Profile

crower: (Default)
crower

February 2018

S M T W T F S
    123
45678910
11121314151617
181920212223 24
25262728   

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 27th, 2026 11:59 pm
Powered by Dreamwidth Studios