Руковожу хостингом одной некрупной, но гордой компании. Перлов при работе с клиентами много, но больше бывает при общении с разработчиками.
Решили мы тут озаботится вопросом, не расширить ли парк серверов баз данных — ресурсы есть, но нужно ли? Стали собирать статистику. Самым большим по количеству (75%) и объёму (90%) запросов оказался сайт Самого Важного Клиента, который занимал чуть ли не половину дискового пространства всего хранилища и отвечал за 60% всего трафика. Решили посмотреть, что они такое туда пишут.
Оказалось, разработчики этого чуда решили оптимизировать SQL-запросы и использовали какую-то чудо-библиотеку, которая на лету оптимизировала обращения к MySQL-кластеру. Результат оптимизации выглядел следующим образом: сначала происходит обращение на сервер с целью создания физического плана запроса, ждёт подтверждения, затем в него подсовываются входные параметры, забирается результат, но тут происходит самое страшное — физический план запроса удаляется. То есть при каждом однотипном запросе физический план создаётся заново. Но и это не самое страшное. Половина всех запросов выглядела так:
INSERT INTO `statistic_logs` VALUES ...
В результате простейший запрос, занимающий одну строку и являющийся элементарной операцией MySQL-сервера, после «оптимизации» занимал восемь строк и выполнялся в полтора раза медленнее.
Многие работающие в саппорте жалуются на неадекватных пользователей, а как быть, если саппорт сам не знает ничего о том, что поддерживает?
История произошла по причине моего увлечения опенсорсом. Как не крути, а GNU/Linux от известных мейнтейнеров работает на старом железе гораздо надёжнее и стабильнее, нежели «популярная» ОС. Всё началось с малых экспериментов над одной программой для оборудования с ЧПУ. Поставил Дебиан и Вайн, первый же блин вышел комом — нет связи по COM-порту, точнее, есть, но очень нестабильная. Погуглив, нашёл патч для драйвера, исправлявший этот недостаток. Накладывать пришлось, конечно же, напильником, благо С я немного знал.
Всё прекрасно работало в течение нескольких месяцев, пока не пришло обновление. Оно-то тоже работало, да вот только базы данных в этот раз должны были быть в клиент-серверном варианте, да ещё и через сторонний драйвер. Из-за некоторых ограничений Вайн не мог такие костыли поддерживать, но я немного покопался и нашёл-таки способ использовать локальные базы.
Далее состоялась феерическая переписка с саппортом, который уверял, что баз данных в нужном мне формате не существует и существовать не может. Плюнув на это, за два вечера была методом проб и ошибок составлена локальная БД, но вот беда: в программе использовали серверный SQL, который неприменим для локального использования.
Это уже была серьёзная проблема, которую пришлось «выпилить» банальным hex-редактором, благо сама же программа выдавала окна с указанием ошибок в синтаксисе запросов. Так-то, лучший саппорт — голова на плечах.
Третьего дня свёл знакомство с одной проблемой. Наши одиночества встретились весьма прозаичным способом: я жил и писал странные команды в консоли, а она родилась хоть и тихо, но зато сразу всех обрадовала — точнее, сначала заказчиков. Потом они вместе пришли и всем своим видом показали: «А вот и мы!» Бага была из разряда пренеприятнейших — пряталась умело, возникала внезапно и при возникновении сразу знала, куда наносить удар. Именно в то место, где сходятся интересы всех без исключения — в финансовые расчёты.
В процессе ловли ошибки я много времени провёл наедине с базой данных. Нужно упомянуть, что я работаю в области строительства цифрового телевидения. Так вот, обнаружилось странное — приличное количество абонентов по непонятной причине подписывает и отписывает один и тот же сервис по несколько раз за день, да и еще с завидным упорством повторяет эти действия на протяжении месяцев! Причину такого странного поведения понять стало даже интереснее, чем ловить багу, про которую уже все забыли. Так как в базе все сущности связаны хитросплетением ID, «констрейнтов» и прочих «форейнкеев», на первый взгляд кажется, что люди просто любят мелькание менюшек на телевизоре.
Всё обрело смысл, как только я выцепил человеческое имя этого сервиса. Им оказался пакет каналов «Досуг». Да-да, набор каналов с замечательными девушками и их хирургическими достижениями. Изучение результатов выполнения запросов показало, что для удовлетворения среднестатистическому пользователю нужно от двух до пятнадцати минут. Как правило, люди склонны к изучению своего внутреннего мира с утра и после работы. И самое главное — все склонны скрывать свою страсть к подобного рода времяпрепровождению, так как отключают сервис сразу после выполнения задуманного.
Закончив интересный анонимный соцопрос, я подумал: «Как же хорошо быть айтишником!»
Не секрет, что хороший программист должен обладать даром предвидения, чтобы знать, что нужно заранее предусмотреть в проекте и к каким модификациям проект должен быть готов. Те, у кого такого дара нет, либо выкручиваются перестраховками, либо по нескольку раз переписывают одну и ту же программу.
Недавно мне на глаза попались исходники одного скрипта регистрации на сайте; среди прочих была и графа «пол» — пара радиокнопок. Не знаю, сколько раз человек, писавший этот скрипт, сталкивался с бесконечно меняющимися требованиями заказчиков, но этот перл, по-моему, является верхом перестраховочной паранойи.
Среди прочих таблиц в базе данных была таблица «sexes»: идентификатор и название, две строки. В профиле у каждого пользователя хранился идентификатор нужной строки. Интересно, предусмотрел ли что-нибудь автор на тот случай, если на ключ этой таблицы перестанет хватать четырёх байт?
Довелось мне работать в местном интернет-провайдере. Помимо предоставления телекоммуникационных услуг, фирма зарабатывала на создании различных тематических сайтов. Одним из них был сервис по отсылке SMS-сообщений, которые клиенты нашей сети могли отправлять бесплатно.
Я имел отношение к разработке этого сервиса и обслуживал всех клиентов в случае возникновения проблем. Все правки производились непосредственно в консоли базы данных, потому как админку было писать недосуг.
В один прекрасный день клиент пришёл прямо к нам в офис и попросил поменять пароль на его логин в SMS-системе. Быстро найдя в базе номер его записи, я слепым десятипальцевым методом быстро ввожу типичный запрос:
update users set password='newpass' where id - 1234;
...и жму Enter. Вместо знака равенства нажалась клавиша «минус». В результате база данных, вычислив разность между номерами клиентов и заданным числом, поменяла пароли всем, кроме этого клиента.
Следующие два часа ушли на восстановление паролей недельной данности, а ещё где-то месяц мы отвечали на гневные звонки тех, кто за эту неделю менял свой пароль.
Один из серверов был сильно перегружен клиентскими сайтами и в конце концов перестал отдавать контент: пошел в своп, а load average зашкаливал за полсотни. Начинаем вместе с клиентом выяснять, чем же его так. В выводе top налицо активно лопающий память MySQL-сервер, каковым фактом мы радуем клиента и рекомендуем оптимизировать запросы. Клиент отвечает: «Сайт не использует базу данных этого сервера, а работает с удалённой базой».
Сообщаем клиенту, что его сайт на его же сервере не один, и остальные всё-таки потребляют ресурсы и «укладывают» машину. Ответ клиента ошеломил:
— Ммм, а сколько сайтов находится на нашем сервере, и каких именно?
Несколько лет назад наша контора внедряла большую ERP-систему в большой конторе. Всё было настроено, отлажено, проверено, данные загружены. Наступило замечательное время, которое у консультантов называется UAT. Восхищённые/раздражённые юзеры полезли грязными руками тыкать в кнопочки. Одним из юзеров был важный дядя (не Сам, но почти).
Итак, модуль по работе с кадрами. Дядя, не мудрствуя лукаво, запрашивает свои собственные данные и выпадает в осадок. Мало того, что он отображается в системе как женщина, так он (она?) ещё и беременный! Так как кодят систему в основном индусы, огрехи всплывают часто. Как оказалось, забеременеть можно не только по естественным причинам, но и в результате неправильного использования nvl и decode.
Ведь обещали миллион условных енотов первому мужчине, который родит. Можно сказать, дядя шел к успеху, но не подфартило. Исправленный код выпустили через неделю. А какая была мечта!
Много лет в крупном операторе фиксированной связи российского масштаба не было постоянного и квалифицированного системного администратора. Люди приходили и уходили, а знания, пароли и учётные записи уходили вместе с ними. Сервера безвозвратно падали, с ними падал софт, включая базы данных, хитрый, созданный ещё в советское время биллинг, подсистемы программирования кристаллов таксофонных карт и прочее.
Вот уже не осталось носителей знаний, и даже некому было поставить клиент Navision Axapta. Каково же было моё изумление, когда хрупкая девушка попросила меня подойти к ней! На экране — удалённая оснастка, вход в локальную базу и какой-то мелкий вопрос, как правильно делать бэкап. Оказалось, что многие годы эта героическая девушка из бухгалтерии по инструкции еженедельно делала бэкап самой важной базы, как ей и заповедовал один из основоположников всей этой системы.
Был я айтишником в одном турагентстве. Как-то, шерстя базу данных, я нашёл информацию о ценах в отелях на ближайшие три года. Спрашиваю у генерального директора, как это так: то ли у нас ясновидец в штате появился, то ли отели по три года не меняют цены в условиях инфляции? Босс ответил, что данные туда попали по ошибке, и их надо удалить.
Всего один короткий запрос. Всего две забытые кавычки:
delete from prices where price_date>unix_timestamp(2009-12-31)
Сервер радостно подсчитал: 2009 – 12 – 31 = 1968. Как и было заказано, база данных грохнула цены на все даты позже 1968 секунд от начала юникс-эпохи (то есть после 0 часов 32 минут 42 секунд 1 января 1970 года). На тот момент не существовало не только самой фирмы, но даже и самого гендиректора.
В итоге все отели лишились всех цен. Вытаскивать в авральном режиме из бэкапов несколько сотен тысяч строк вручную было ой как весело...
8 марта 2010
В этот совершенно не-айтишный праздник мы ни в коем случае не можем забыть о вас, любимые наши женщины! Счастья вам и бесперебойной работы вашим компьютерам!