Часть 1. Прайс из Китая
Действующие лица:
Таня — менеджер по закупкам. Мыслит категориями «красивенько», «быстренько» и «скидочки». В руках у неё флешка с прайс-листом поставщика на 300 000 строк.
Джуниор (Данила) — 22 года. Называет себя «Промпт-Архитектором». Уверен, что если код компилируется, то он крутой. Искренне верит, что ИИ уже заменил senior-архитекторов.
Сеньор (Михалыч) — 45 лет. Борода до пупка. Глаза цвета «база данных заблокирована». В руках держит сушёную воблу.
Тимлид (Антон Павлович) — начальник отдела. Уставший человек с поллитровой кружкой кофе, который просто мечтает дожить до пятницы.
Акт первый: Сила правильного промпта
Место действия: ИТ-отдел, где пахнет свежемолотым кофе и термопастой. На стене висит наклейка «Выжили! 1С 7.7 на 8.5», ставшая местной иконой. В углу мерно и мирно шуршит серверная стойка, на которой красуется табличка: «Не трогай, оно работает». Атмосфера дышит абсолютным, почти курортным спокойствием.
Джуниор Данила сидит за новеньким ноутбуком, на котором еще не высохла краска. Он чувствует себя властелином мира. Зачем три года зубрить синтакс-помощник, если у тебя открыто окно передового ИИ, способного сгенерировать код за две секунды? В паре метров от него, глубоко откинувшись в огромном кожаном кресле, восседает Сеньор Михалыч. Его борода помнит блокировки таблиц на платформе 8.0, а во взгляде читается знание всех тайн СУБД. Михалыч не спеша, с хирургической точностью отламывает хвост у сушеной воблы прямо над клавиатурой. У двери за своим столом замер Тимлид Антон Павлович. Он судорожно обновляет почту, пьет кофе из поллитровой кружки и надеется, что этот день пройдет без происшествий.
Данила: (вальяжно потягивая смузи) Антон Павлович, я сегодня написал промпт для ИИ. Задал ему жесткие условия, контекст управляемых форм платформы 1С и клиент-серверное разделение. Вот смотрите, какой промпт получился:
Промпт Данилы для ИИ:
*"Ты — Senior-разработчик 1С. Напиши код для управляемой формы документа.
Создай клиентские процедуры для расчета Суммы при изменении Цены или Количества в табличной части "ПереченьТоваров" через получение текущих данных формы.
Напиши обработчик события "ПриЗаписиНаСервере", который будет выводить в окно сообщений общее количество строк в документе и итог по колонке "Количество".
Оформляй код строго по стандартам 1С, добавляй комментарии."*
И нейросеть мне выдала полностью рабочий код! Любой разработчик может прямо сейчас проверить, скопировать его, вставить себе в конфигуратор:
&НаКлиенте
Процедура ПереченьТоваровКоличествоПриИзменении(Элемент)
// Получаем строку, в которой в данный момент работает пользователь
СтрТабЧасти=Элементы.ПереченьТоваров.ТекущиеДанные;
//Сумма=Цена*Количество
СтрТабЧасти.Сумма=СтрТабЧасти.Цена*СтрТабЧасти.Количество;
КонецПроцедуры
&НаКлиенте
Процедура ПереченьТоваровЦенаПриИзменении(Элемент)
// Получаем строку, в которой в данный момент работает пользователь
СтрТабЧасти=Элементы.ПереченьТоваров.ТекущиеДанные;
//Сумма=Цена*Количество
СтрТабЧасти.Сумма=СтрТабЧасти.Цена*СтрТабЧасти.Количество;
КонецПроцедуры
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Сообщить("Всего в документе "+
ТекущийОбъект.ПереченьТоваров.Количество()+
" строк(и), с количеством товаров "+
ТекущийОбъект.ПереченьТоваров.Итог("Количество")+" шт.");
КонецПроцедуры
Сеньор Михалыч: (внимательно смотрит в монитор Данилы, жует воблу и одобрительно кивает) Хм... А, ведь действительно, код чистый и рабочий. Текущие данные формы получены верно, вызов серверного контекста при записи оптимален, итоги считаются без лишних запросов.Молодец, Данила. Но помни: чтобы ИИ всегда выдавал тебе рабочий код под 1С, нужно знать тонкости в написании промпта и понимать директивы компиляции.
Антон Павлович: (делает большой глоток кофе) Давайте без философии. Главное — чтобы сегодня всё было тихо. У Анастасии Марковны из бухгалтерии сегодня закрытие квартала. Если база упадет хотя бы на минуту, она нас самих на субсчета распилит. Код рабочий — это отлично, но сегодня ничего в прод не внедряем. Так что просто сидим ровно и читаем документацию.
(В этот момент тишина ИТ-отдела раскалывается в щепки. Дверь распахивается с характерным пластиковым хрустом. На пороге возникает менеджер Таня из отдела закупок. Она буквально светится от счастья, в руке у нее победно зажата розовая флешка, а скорость её речи мгновенно перегружает процессор Тимлида.)
Таня: Мальчики, приветик! Спасайте, у меня супер-новость! Я нам такую скидочку у китайских поставщиков выбила, просто космос! Они мне только что на почту скинули прайсик на болты. Маленький такой файлик Excel, всего 300 тысяч позиций! Данечка, ты же мне сделаешь быстренько кнопочку, чтобы всё это красивенько в базу залетело? Мне прям очень надо, у меня через 5 минут созвон с Гуанчжоу!
(Михалыч замирает с куском воблы во рту. Антон Павлович медленно опускает кружку с кофе. Данила радостно расправляет плечи и открывает окно чата с ИИ, чтобы написать новый промпт специально под Танин эксель...) Пальцы джуниора порхают по клавиатуре, пока он формулирует задачу для нейросети, стараясь выглядеть максимально солидно перед Таней.
промпт Данилы для ИИ:
«Мне нужно быстро и кроссплатформенно прочитать файл Excel (.xlsx) на 300 000 строк на стороне сервера под Linux и загрузить данные в созданный нами документ. Напиши самый нативный и современный метод 1С без использования COM-объектов».
ИИ-Кодер: «Отличное решение! Для нативной и кроссплатформенной работы в 1С 8.3 идеально подходит объект ТабличныйДокумент. Он работает на любой ОС и не требует установленного Excel.
Данила: (копирует код и вставляет победно улыбаясь, пока Антон Павлович и Сеньор Михалыч вышли из кабинета) Готово! Таня, вставляй флешку, нажимай «Загрузить»!
Таня: Ой, мальчики! Я нажала, и у меня всё зависло! А Анастасия Марковны из бухгалтерии уже кричит в коридоре, что её выкинуло из системы во время закрытия квартала! И у меня на экране написано: «Ошибка: Недостаточно памяти». Передайте этому «Недостаточно», что он очень невоспитанный!
Сеньор Михалыч: Данила, у нас на сервере рабочий процесс rphost сожрал все 64 Гигабайта оперативной памяти, занял 100% процессора и упал!
Данила: (нервно кликает мышкой, краска сходит с лица) Антон Павлович, ну код же идеален! ИИ написал, что ТабличныйДокумент — это встроенный объект 1С, он обязан работать на Linux! Программа просто думает... там же 300 тысяч строк...
Сеньор Михалыч: (подходит сзади и кладет руку на плечо Даниле) Садись, бери листок и записывай как устроена СУБД (Система Управления Базами Данных) и как приложение 1С будем закладывать туда фундамент ИТ-архитектуры.
(Михалыч решительно отодвигает клавиатуру, берет маркер и подходит к большой офисной магнитной доске)
Данила: (тихо) Михалыч, ну при чем тут СУБД? Код же в 1С написан...
Сеньор Михалыч: 1С сама по себе не умеет делать выборки, сортировать миллионы строк на диске и обеспечивать их сохранность при сбое питания. Всем этим управляет СУБД. 1С — это педаль в салоне (интерфейс, за которым сидит пользователь), а СУБД — это двигатель под капотом, который и выполняет всю тяжелую работу. Ты жмешь педаль в 1С, а СУБД крутит шестеренки на физических дисках сервера.
Михалыч берет маркер и прямо по стрелочкам на доске расписывает Даниле, как строчка кода превращается в байты на диске:( чертит на доске схему и начинает построчно разбирать каждую стрелочку):
Шаг 1. КЛИЕНТ (1С:Предприятие): Менеджер Таня нажимает на клиенте кнопку «Загрузить». Клиентское приложение не работает с базой напрямую — оно лишь отправляет массив данных и команду на сервер.
Кнопка «Загрузить» физически не имеет доступа к таблицам СУБД, а лишь пакует команду, параметры файла и отправляет этот вызов по сети на сервер приложений.
Шаг 2. [ rphost (Сервер приложений 1С) ]:Запрос падает в серверный процесс rphost. Здесь твой код 1С начинает выполняться и построчно переводится (транслируется) в низкоуровневые SQL-запросы, понятные для баз данных.
Главная обязанность сервера приложений 1С: он берёт твой высокоуровневый код встроенного языка (или объектные вызовы вроде Документ.Записать()) и на лету генерирует из них строгие, понятные для СУБД низкоуровневые операторы SQL (такие как INSERT, UPDATE, SELECT).
Шаг 3. СУБД (PostgreSQL / MS SQL):Сервер 1С передает эти SQL-команды на вход СУБД. Внутри СУБД их встречает Движок SQL (Query Processor).
Когда SQL-запрос прилетает из 1С, Движок SQL (Query Processor) не бросается сразу выполнять его вслепую. Он работает как умный навигатор:
Он оценивает входящий текст запроса. Смотрит на статистику базы данных и строит план выполнения (Execution Plan) — то есть выбирает оптимальный маршрут (какие индексы использовать, как связать таблицы). Принимает решение, как максимально эффективно и быстро обработать этот поток данных.
Шаг 4. [ Кэш памяти СУБД ]:СУБД никогда не пишет данные на медленный диск мгновенно. Первым делом новые строки номенклатуры залетают в сверхбыструю оперативную память сервера — Кэш памяти (Buffer Pool) и параллельно фиксируются в логе транзакций.
Когда 1С говорит: «СУБД, запиши новый товар», умная база данных (MS SQL или PostgreSQL) делает два действия одновременно в оперативной памяти:
Кэш памяти (Buffer Pool): СУБД меняет данные в своей оперативке. Это мгновенно. На диск сам товар пока не пишется.
Лог транзакций (WAL): СУБД обязана сделать текстовую запись-черновик в специальный журнал: «Данила создаёт строку №1». Этот лог — гарантия того, что если прямо сейчас выключится свет, СУБД при перезагрузке прочитает этот черновик и восстановит данные.
Что ломается, если транзакция гигантская (на 300 000 строк)?
Пока Данила не скажет финалу транзакции Зафиксировать, СУБД находится в состоянии «боевой тревоги»:
Журнал (лог) раздувается: СУБД не имеет права стирать этот черновик с диска. Вдруг на 299 999-й строке у Тани выдернется флешка? Тогда СУБД должна будет пройти по журналу назад и стереть всё, что Данила успел накодить (сделать откат — Rollback). Журнал забивает весь диск сервера.
Диски ложатся в 100% (I/O Bottleneck): Сервер начинает непрерывно сбрасывать этот гигантский лог из памяти на жесткий диск, диски не справляются с потоком, и вся система начинает жутко тормозить.
Замок на таблице (Exclusive Lock): Чтобы в этот черновик никто тайно не вписал другие данные (например, Анастасия Марковна со своей накладной), СУБД вешает «монопольный замок» на всю таблицу товаров.
Шаг 5. [ HDD / SSD Сервера ]:И только после этого, когда кэш заполнен или транзакция закрыта, СУБД выполняет физическую запись в файлы данных на жесткие диски сервера. Данные сохранены навсегда.
Что такое «Фиксация» (Commit) на физическом уровне?
Когда в коде 1С срабатывает команда ЗафиксироватьТранзакцию(), СУБД получает команду COMMIT. До этого момента все 300 000 болтов висели в воздухе. Фиксация — это юридическая точка невозврата. СУБД проверяет, что все строчки успешно обработаны, ошибок нет, и ставит в логе транзакций (WAL-журнале) окончательный статус: «Транзакция Данилы завершена успешно, данные подтверждены».
2. Почему СУБД не пишет данные на диск сразу? Жесткие диски (HDD) и даже твердотельные накопители (SSD) — это самая медленная часть любого сервера. Оперативная память работает в тысячи раз быстрее. Если бы СУБД при создании каждого отдельного болта сразу дергала головку жесткого диска или перезаписывала ячейки SSD, сервер бы мгновенно «встал». Поэтому СУБД применяет упреждающую запись: она мгновенно меняет данные прямо в оперативной памяти — в так называемом Кэше страниц (Buffer Pool), а на диск пишет только короткую строчку в лог транзакций. В итоге на диске сами файлы базы данных (.mdf или таблицы Postgres) пока остаются старыми, а новые данные существуют только в оперативке.
3. Как происходит «Физическая запись в файлы данных»?Процесс переноса из быстрой памяти на медленный диск называется Checkpoint (Контрольная точка) или работа асинхронного писателя (Lazy Writer / Background Writer).
Шаг А: СУБД копит измененные Данилой страницы данных в оперативке. Эти страницы в мире СУБД называются «грязными страницами» (Dirty Pages) — то есть это данные, которые уже изменились в памяти, но еще не записаны на диск.
Шаг Б: Как только транзакция Данилы зафиксирована, или когда оперативная память СУБД начинает переполняться, включается внутренний системный поток СУБД.
Шаг В: Этот поток берет «грязные страницы» из оперативки, пакует их в ровные блоки и последовательно, не нагружая процессор, сбрасывает (делает Flush) на физические жесткие диски сервера (HDD/SSD).
Шаг Г: Данные физически перезаписываются в файлы базы. Только после этого страницы в памяти становятся «чистыми», а лог транзакций на диске можно очистить.
Сеньор Михалыч: (опускает маркер на стол) Вот так, Данилка, выглядит идеальный путь данных. Красивая цепочка, правда? А теперь давай разберем, как твой код устроил погром на каждом метре этой схемы.
Принцип 1. Клиент-Серверная архитектура и память приложений.
Платформа 1С сама по себе не хранит файлы на диске, а выступает лишь «переводчиком» твоего кода в SQL-запросы для СУБД. Твой ИИ подсказал метод ТабличныйДокумент.Прочитать(), который выполняется на стороне сервера приложений в процессе rphost. Когда rphost начинает читать этот файл, внутренний C++ движок платформы пытается воссоздать в оперативной памяти полную визуальную объектную модель документа. На каждую из миллионов ячеек, на каждый чих со стилем, шрифтом, границей или формулой платформа 1С создаёт тяжелый внутренний объект структуры встроенного языка (область ячеек, форматные свойства и метаданные).Из-за этого колоссального объема внутренних структур 1С скрытый XML-архив весом 50 Мб раздулся в оперативной памяти сервера до 70 Гигабайт. Операционная система Linux увидела, что процесс rphost критически превысил лимиты выделения ресурсов, поэтому сработал механизм защиты OOM Killer — он принудительно завершил работу сервера 1С, остановив работу всей компании.
Вывод первого урока: rphost — это память приложения. Ее нельзя засорять визуальными моделями документов на стороне сервера. Для больших файлов память должна использоваться как «проточный фильтр» — прочитал строчку текста, обработал, забыл, пошел к следующей. Это называется потоковым чтением.
Принцип 2. Что такое Транзакция и принцип ACID
Данила: (завороженно смотрит на доску) Ладно, с памятью приложения понятно — rphost лопнул от Таниных ячеек. Но если бы у нас было не 64 гигабайта оперативки, а терабайт, код бы выполнился?
Сеньор Михалыч: Он бы дошел до следующего этапа и там бы намертво заклинил саму СУБД. Потому что твой ИИ написал код, который пытается загнать все 300 000 строк в базу одной транзакцией.
Что такое транзакция? Это фундаментальное понятие в СУБД. Это группа последовательных операций с базой данных, которая представляет собой единую логическую единицу работы. Транзакция работает по строгому международному стандарту ACID:
A (Atomicity) — Атомарность: Транзакция будет выполнена либо полностью, либо не выполнена вообще. Никаких «половинок». Если у тебя загрузится 299 999 болтов, а на последнем произойдет ошибка — СУБД сотрет всё, что ты сделал до этого, вернув базу в исходное состояние.
C (Consistency) — Согласованность: Каждая успешная транзакция фиксирует только допустимые результаты. База переходит из одного качественного состояния в другое, не нарушая логических связей и индексов.
I (Isolation) — Изолированность: Транзакции, выполняемые параллельно, не должны влиять друг на друга. То, что делаешь ты в своей транзакции, не должно быть видно Анастасии Марковне, пока ты не закончишь.
D (Durability) — Стойкость: Если СУБД сказала, что транзакция зафиксирована, данные железно записаны на диск, и даже если в следующую секунду в серверной выключится свет — данные не пропадут.
Данила: Красивая теория. А как она ломает сервер на практике?
Принцип 3. Лог транзакций (Transaction Log) и дисковая подсистема
Сеньор Михалыч: А на практике, чтобы обеспечить эту самую Атомарность (Atomicity) и Стойкость (Durability), СУБД использует специальный инструмент — Лог транзакций (журнал предзаписи, WAL в PostgreSQL).
Когда СУБД получает команду записать элемент, она не бежит сразу менять файлы самой базы данных на жестком диске — это слишком медленно. СУБД сначала пишет эту операцию в лог транзакций последовательным потоком. Лог — это черновик. СУБД говорит: «Я помню, что Данила хочет записать Болт №1, Болт №2...».
И пока твоя гигантская транзакция на 300 000 строк не завершится командой ЗафиксироватьТранзакцию(), СУБД обязана держать в логе транзакций всю эту колоссальную простыню данных! Зачем? Чтобы если на 299 999-й строке у Тани выдернется флешка, СУБД могла выполнить команду Rollback (откат) — пройти по логу назад и вернуть базу в исходную точку.
Когда ты пихаешь 300 000 элементов в одну транзакцию, лог транзакций раздувается до неприличных размеров, забивает весь кэш СУБД, начинает бешено писать временные файлы на диск, дисковая подсистема сервера встает в стопроцентную полку (I/O Bottleneck), и сервер зависнет.
Принцип 4. Блокировки таблиц (Locks) и конкурентный доступ
Данила: (сглатывает смузи, в руке карандаш) Михалыч... а при чем тут главбух Анастасия Марковна? Почему её выкинуло, если я работал со справочником Номенклатуры, а она — со своими налогами и накладными?
Сеньор Михалыч: (чертит жирную линию на доске) А вот тут вступает в силу свойство Изолированности (Isolation) из принципа ACID. Чтобы твоя транзакция не перемешалась с чужими данными, СУБД использует Блокировки (Locks).
Когда твоя транзакция начинает создавать Номенклатуру, СУБД вешает на таблицы справочника и связанных с ним регистров Монопольную блокировку (Exclusive Lock). Для СУБД это выглядит так: «Внимание! Данила открыл транзакцию. Пока он не закончит, я закрываю эти таблицы на замок. Никто другой не имеет права записывать сюда данные и менять индексы!».И вот Анастасия Марковна пытается провести накладную. В этой накладной есть список товаров. При проведении документы 1С делают проверку остатков, обращаются к таблицам Номенклатуры, пытаются обновить индексы. Анастасия Марковна стучится в базу, а СУБД ей говорит: «Жди. Таблицы заблокированы Данилой. У него там транзакционный лог горит и 300 тысяч болтов едут из Китая».
Сессия Анастасии Марковны встает в очередь (Lock Timeout). Она ждет 20 секунд, ждет 40 секунд... Время ожидания блокировки, установленное в кластере 1С, истекает. Платформа понимает, что СУБД ей данные не отдаст, аварийно прерывает сессию бухгалтера и выплевывает ей на экран ошибку: «Конфликт блокировок при выполнении транзакции». Квартальный отчет сорван.
Данила: (смотрит на маркерную доску как на откровение) То есть... ИИ выдал мне код, который синтаксически правильный, но не учел архитектуру СУБД.
Сеньор Михалыч: Данила, промпт я тебя научу правильно писать, но отныне все свои действия согласовывай со мной!
Как вы видите, если бы сеньор проверил работу джуниора, тогда гарантированно база не слетела бы.
В следующей части: Суровый Сеньор Михалыч переименует файл Тани в ZIP-архив, покажет истинную изнанку файлов .xlsx изнутри и напишет сверхбыструю загрузку через ЧтениеXML.
Вступайте в нашу телеграмм-группу Инфостарт