Минимальные системные требования
Платформа:
- Windows 10 версии 1607 или более поздней
- Windows 11
Разрядность: x64
Процессор: 4-ядра
ОЗУ \ ПЗУ: 8GB \ SSD 120 ГБППС БАРС 165.3 (кастом) или 166 и выше
Bars.ETL — инструмент для создания конвейеров (pipelines) перемещения и преобразования данных между различными источниками. Конвейер состоит из последовательности шагов, каждый из которых выполняется определённым плагином.
Конфигурация описывается в JSON-формате и размещается в файле configs/pipelines.json.
Все необходимые дистрибутивы находятся в каталоге
{
"id": "unique-pipeline-id",
"name": "Pipeline Name",
"description": "Pipeline description",
"version": "1.0.0",
"steps": [
{
"name": "Step 1",
"plugin": "PluginName",
"params": {},
"enabled": true,
"timeout": "00:30:00"
}
],
"settings": {},
"schedule": {}
}
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| enabled | boolean | true | Включено ли расписание |
| cron | string | "0 0/30 * * ?" | Cron-выражение |
| timeZone | string | null | Временная зона (напр. "Europe/Moscow") |
| misfirePolicy | string | "DoNothing" | Политика при пропуске запуска |
| disallowOverlap | boolean | true | Запретить параллельное выполнение |
Примеры Cron-выражений (формат Quartz: сек. мин. ч. д.м. мес. д.н.):
| Выражение | Описание |
|---|---|
0 0/15 * * * ? |
Каждые 15 минут |
0 0/30 * * * ? |
Каждые 30 минут |
0 0 * * * ? |
Каждый час |
0 0 6 * * ? |
Каждый день в 6:00 |
0 0 0 * * ? |
Каждый день в полночь |
0 0 9 ? * MON-FRI |
По будням в 9:00 |
0 0 9 ? * MON |
Каждый понедельник в 9:00 |
0 0 0 1 * ? |
1-го числа каждого месяца |
0 0 0 L * ? |
В последний день каждого месяца |
*/15 * * * * ?— каждые 15 секунд, не минут. Для минут используйте0 0/15 * * * ?.
Извлечение данных из реляционных баз данных.
Поддерживаемые провайдеры: SqlServer, PostgreSQL, MySQL, SQLite
| Параметр | Тип | Обяз. | По умолчанию | Описание |
|---|---|---|---|---|
| provider | string | Да | — | Тип базы данных |
| connectionString | string | Да | — | Строка подключения к БД |
| query | string | Нет* | — | SQL-запрос для извлечения данных |
| queryFile | string | Нет* | — | Путь к файлу с SQL-запросом |
| batchSize | int | Нет | 1000 | Размер пакета при чтении |
| commandTimeout | int | Нет | — | Таймаут выполнения запроса (сек.) |
Необходимо указать либо
query, либоqueryFile.
Сохранение данных в реляционные базы данных.
| Параметр | Тип | Обяз. | По умолчанию | Описание |
|---|---|---|---|---|
| provider | string | Да | — | Тип базы данных |
| connectionString | string | Да | — | Строка подключения к БД |
| table | string | Да | — | Имя целевой таблицы |
| mode | string | Нет | "sync" | Режим: "sync" или "full" |
| createMode | string | Нет | "CreateIfNotExists" | Режим создания таблицы |
| batchSize | int | Нет | 1000 | Размер пакета для вставки |
| useHash | boolean | Нет | false | Использовать хэш для сравнения |
| deleteMissing | boolean | Нет | true | Удалять отсутствующие записи (sync mode) |
| truncateBeforeLoad | boolean | Нет | false | Очистить таблицу перед загрузкой |
| uniqueKey | string[] | Да* | [] | Колонки уникального ключа |
| indexes | object[] | Нет | [] | Определения индексов |
| columns | object | Нет | null | Явное указание типов колонок |
uniqueKeyобязателен для режима"sync".
Режимы работы:
uniqueKey), удаление отсутствующих (если deleteMissing: true)truncateBeforeLoad: true) и вставка всех записейГенерация статических данных из конфигурации (для тестирования).
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| data | array | Да | Массив объектов с данными |
{
"id": "financial-panel-sync-v1",
"name": "Синхронизация финансовой панели",
"steps": [
{
"name": "Загрузка данных из БАРС",
"plugin": "DbFetch",
"params": {
"provider": "SqlServer",
"connectionString": "Server=DataBase;Database=Base1;User ID=sa;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True",
"queryFile": "D:\\path\\to\\request.sql",
"commandTimeout": 120,
"maxRows": 1000000,
"syncWindow": {
"type": "time",
"columnName": "TransTime",
"fromUtc": "2026-01-01T00:00:00Z",
"toUtc": "2026-02-01T00:00:00Z",
"window": "P5D"
}
}
},
{
"name": "Сохранение в Bitrix таблицу",
"plugin": "DbSave",
"params": {
"provider": "SqlServer",
"connectionString": "Server=DataBase;Database=Base2;User ID=sa;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True",
"table": "BitrixDataTable",
"mode": "full",
"createMode": "CreateIfNotExists",
"indexes": [{ "name": "idx_TransTime", "columns": ["TransTime"], "unique": false }],
"batchSize": 5000
}
},
{
"name": "Сохранение в BI таблицу",
"plugin": "DbSave",
"params": {
"provider": "PostgreSQL",
"connectionString": "Host=localhost;Port=5432;Database=TestSynch;Username=postgres;Password=***",
"table": "AlterTableBitrix",
"mode": "full",
"createMode": "CreateIfNotExists",
"indexes": [{ "name": "idx_TransTime", "columns": ["TransTime"], "unique": false }],
"batchSize": 5000
}
}
],
"schedule": {
"enabled": true,
"cron": "*/15 * * * * ?",
"timeZone": "Europe/Moscow",
"misfirePolicy": "DoNothing",
"disallowOverlap": true
}
}
{
"id": "load-static-dictionary",
"name": "Load Static Dictionary",
"steps": [
{
"name": "Generate dictionary data",
"plugin": "StaticDataPlugin",
"params": {
"data": [
{ "code": "RUB", "name": "Russian Ruble", "symbol": "₽" },
{ "code": "USD", "name": "US Dollar", "symbol": "$" },
{ "code": "EUR", "name": "Euro", "symbol": "€" }
]
}
},
{
"name": "Save to database",
"plugin": "DbSavePlugin",
"params": {
"provider": "PostgreSQL",
"connectionString": "Host=localhost;Database=app;",
"table": "currencies",
"mode": "sync",
"uniqueKey": ["code"],
"deleteMissing": true
}
}
]
}
Переменная
@user— типINT, числовой идентификатор суперсчёта в БАРС. Не является GUID/UUID.
DECLARE @from DATETIME;
DECLARE @to DATETIME;
DECLARE @user INT;
SET @from = '2026-02-01'; -- формат YYYY-MM-DD
SET @to = '2026-02-16'; -- формат YYYY-MM-DD
SET @user = 1000000; -- заменить реальным ID суперсчёта
IF OBJECT_ID('tempdb..#v_toData') IS NOT NULL DROP TABLE #v_toData;
IF OBJECT_ID('tempdb..#v_fromData') IS NOT NULL DROP TABLE #v_fromData;
SELECT * INTO #v_toData
FROM (
SELECT v.* FROM v_CrossTransactions v
WHERE v.TransTime >= @from AND v.TransTime < @to
AND v.SuperAccountIdTo = @user
UNION
SELECT v.* FROM v_CrossTransactionsClientMoney v
WHERE v.TransTime >= @from AND v.TransTime < @to
AND v.SuperAccountIdTo = @user
) q;
SELECT * INTO #v_fromData
FROM (
SELECT v.* FROM v_CrossTransactions v
WHERE v.TransTime >= @from AND v.TransTime < @to
AND (
v.SuperAccountIdFrom = @user
OR (v.SuperAccountIdTo = @user
AND (v.StockTypeFrom IN (62, 63) OR v.CrossStockTypeFrom IN (62, 63)))
)
UNION
SELECT v.* FROM v_CrossTransactionsClientMoney v
WHERE v.TransTime >= @from AND v.TransTime < @to
AND v.SuperAccountIdFrom = @user
) q;
-- ... основной SELECT (см. полный текст запроса) ...
DROP TABLE #v_toData;
DROP TABLE #v_fromData;
{
"id": "financial-panel-sync-v2",
"name": "Синхронизация финансовой панели (файловый запрос)",
"steps": [
{
"name": "Загрузка данных из БАРС",
"plugin": "DbFetch",
"params": {
"provider": "SqlServer",
"connectionString": "Server=DataBase;Database=BaseOne;User ID=sa;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True",
"queryFile": "D:\\path\\to\\requestBitrix.sql",
"commandTimeout": 120,
"maxRows": 1000000,
"syncWindow": {
"type": "time",
"columnName": "TransTime",
"fromUtc": "2026-01-01T00:00:00Z",
"window": "P5D"
}
}
},
{
"name": "Сохранение в Bitrix таблицу",
"plugin": "DbSave",
"params": {
"provider": "SqlServer",
"connectionString": "Server=DataBase;Database=BaseTwo;User ID=sa;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True",
"table": "BitrixDataTable",
"mode": "full",
"createMode": "CreateIfNotExists",
"indexes": [{ "name": "idx_TransTime", "columns": ["TransTime"], "unique": false }],
"batchSize": 5000
}
},
{
"name": "Сохранение в BI таблицу",
"plugin": "DbSave",
"params": {
"provider": "PostgreSQL",
"connectionString": "Host=localhost;Port=5432;Database=Synch;Username=postgres;Password=***",
"table": "AlterTableBitrix",
"mode": "full",
"createMode": "CreateIfNotExists",
"indexes": [{ "name": "idx_TransTime", "columns": ["TransTime"], "unique": false }],
"batchSize": 5000
}
}
],
"schedule": {
"enabled": true,
"cron": "*/15 * * * * ?",
"timeZone": "Europe/Moscow",
"misfirePolicy": "DoNothing",
"disallowOverlap": true
}
}
{ "type": "full" }
Используется автоматически, если тип не указан.
{
"type": "time",
"columnName": "OrderDate",
"fromUtc": "2024-01-01T00:00:00Z",
"window": "P5D",
"lastProcessedUtc": "2024-01-01T12:00:00Z"
}
| Параметр | Описание |
|---|---|
columnName |
Имя колонки с датой/временем |
fromUtc |
Начало диапазона (UTC, включительно) |
window |
Размер выборки (формат ISO 8601) |
lastProcessedUtc |
Последняя обработанная дата (watermark) |
{
"type": "range",
"columnName": "MasterTransactionId",
"chunkSize": 1000,
"fromInclusive": 5048181
}
Всегда добавляйте
ORDER BYпо колонке изcolumnName.
| Переменная | Описание |
|---|---|
@wm_from |
Начало окна (включительно) |
@wm_to |
Конец окна (исключительно) |
SELECT * FROM MasterTransaction
WHERE MasterTransactionId >= @wm_from
AND MasterTransactionId < @wm_to
ORDER BY MasterTransactionId;
@wm_from/@wm_toдоступны только при указанииwindowвTimeSyncWindow. Без него запрос завершится ошибкой.
При повторном запуске pipeline с тем же id без удаления etl_state.db запуск не происходит. Ошибок нет, в логе — 0 триггеров.
Решение: Удалить etl_state.db или задать новый уникальный id.
DbFetch execution failed: Необходимо объявить скалярную переменную "@wm_from".
Возникает при использовании @wm_from / @wm_to без указания window в TimeSyncWindow.
Решение: Всегда указывайте window при использовании этих переменных.
При повторном выполнении pipeline не проверяется соответствие уже загруженным данным. Может приводить к неконсистентности без уведомления.
22021: неверная последовательность байт для кодировки "UTF8": 0x00
Причина: PostgreSQL чувствителен к нулевым байтам при передаче через COPY.
Решение: Вычищать нулевые байты перед передачей в PostgreSQL.
Window did not advance after iteration 1. Infinite loop detected.
Window: {"type":"range","columnName":"MasterTransactionId","lastProcessedKey":null}
Причина: При lastProcessedKey: null окно не сдвигалось.
Решение: Исправлено. Добавлено предупреждение при отсутствии ORDER BY:
ВНИМАНИЕ! Используется инкрементальная загрузка (Window=RangeSyncWindow),
но в SQL запросе не найден 'ORDER BY'. Возможна потеря данных!
batchSize: 1000–5000. Для больших объёмов увеличьте channelCapacityuniqueKeytimeout для длительных операций