Как исправить ошибку Invalid argument при создании табличного пространства PostgreSQL для 1С на сетевом диске?

Системный администратор 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При администрировании баз данных 1С:Предприятие на СУБД PostgreSQL администраторы часто сталкиваются с необходимостью оптимизации дискового пространства. Одним из очевидных решений кажется вынос файлов базы данных или отдельных таблиц на удаленный сервер или сетевое хранилище (NAS) с помощью механизма табличных пространств (tablespace). Однако при попытке указать сетевой UNC-путь вида \\server\share\ система выдает критическую ошибку. Рассмотрим, почему это происходит и как решить данную проблему несколькими способами.

Анализ проблемы и логов ошибки

Рассмотрим стандартную ситуацию. Администратор пытается перенести базу данных «1С:Управление торговлей» на СУБД PostgreSQL, расположенную на Windows-сервере, во вновь созданное табличное пространство на удаленном сетевом ресурсе. При выполнении SQL-запроса по переносу или созданию базы данных СУБД возвращает ошибку, а в логах PostgreSQL регистрируются следующие записи:


WARNING: could not open directory "pg_tblspc/53730430/PG_9.6_201608131/53834047": No such file or directory
ERROR: could not create directory "pg_tblspc/53730430/PG_9.6_201608131/53834047": Invalid argument
STATEMENT: ALTER DATABASE "ut-g" SET TABLESPACE ger;

Основной маркер проблемы здесь — системная ошибка Invalid argument (недопустимый аргумент) при попытке СУБД создать каталог внутри папки pg_tblspc. Выясним глубокие технические причины такого поведения операционной системы и СУБД.

Почему PostgreSQL под Windows не работает с сетевыми UNC-путями напрямую?

Проанализируем архитектуру СУБД PostgreSQL. Механизм табличных пространств в ней реализован через создание файловых ссылок. В каталоге установки СУБД (внутри папки data/pg_tblspc) создаются указатели на реальные физические каталоги, где хранятся файлы таблиц.

В операционной системе Windows для реализации этих указателей СУБД PostgreSQL по умолчанию использует механизм NTFS Junction Points (точки соединения операционной системы). У этого механизма есть жесткое архитектурное ограничение: точки соединения могут указывать исключительно на локальные пути файловой системы NTFS. Они физически не умеют работать с сетевыми путями UNC (начинающимися с двойного обратного слэша \\).

Когда мы выполняем команду создания табличного пространства, указывая сетевую папку, PostgreSQL пытается создать файловую связь типа Junction. Windows блокирует эту операцию и возвращает ошибку недействительного аргумента (Invalid argument), в результате чего создание или перенос базы данных аварийно завершается.

Помимо ограничений файловой системы, существуют еще две серьезные проблемы:

  1. Контекст безопасности службы Windows. По умолчанию служба СУБД (например, postgresql-x64-14) запускается под локальной системной учетной записью (NETWORK SERVICE или локальным пользователем postgres). Этот пользователь не имеет никаких прав доступа к ресурсам локальной сети и другим серверам. Даже если вы подключили сетевой накопитель как диск Z: под своей учетной записью администратора, служба СУБД этот диск просто «не увидит», так как службы работают в изолированном окружении (Session 0).
  2. Опасность повреждения данных (Data Corruption). Файловая система СУБД требует строгой синхронизации транзакций на физический диск (операции fsync). Протоколы сетевого доступа к файлам (SMB/CIFS) не гарантируют абсолютной надежности выполнения этих низкоуровневых команд. При малейшем сетевом сбое, потере пакетов или перезагрузке файлового сервера база данных 1С гарантированно получит повреждение таблиц (состояние «dirty read» или разрушение заголовков файлов данных).

Разберем три основных метода решения этой проблемы — от наиболее надежного к компромиссным.

Решение 1. Использование быстрых локальных дисков (Рекомендуемый вариант)

Для высоконагруженных систем, таких как базы данных 1С:Предприятие, настоятельно рекомендуется использовать только локальные физические накопители (желательно твердотельные диски SSD или NVMe Enterprise-класса). Если на основном системном диске сервера СУБД заканчивается свободное место, оптимальным решением будет:

  1. Установить дополнительный физический накопитель непосредственно в сервер СУБД.
  2. Инициализировать диск в операционной системе, отформатировать его в файловую систему NTFS (рекомендуемый размер кластера для баз данных — 64 КБ).
  3. Назначить диску букву (например, D:\) или примонтировать его в пустую папку на диске C:\.
  4. Создать на новом локальном диске папку для СУБД (например, D:\pg_data_ts\).
  5. Предоставить пользователю, от имени которого запущена служба PostgreSQL, полные права доступа к этой папке.
  6. Создать табличное пространство стандартными средствами СУБД, указав локальный путь.

Решение 2. Использование сетевого хранилища через протокол iSCSI (Лучшая альтернатива для SAN/NAS)

Если физически установить диски в сервер невозможно, а свободное место есть только на удаленном сетевом хранилище (NAS или SAN), подключать его необходимо не как сетевую папку (SMB), а как блочное устройство. Для этого используется протокол iSCSI.

При таком подходе удаленный дисковый массив будет восприниматься операционной системой Windows как полноценный локальный жесткий диск, подключенный по шине SCSI. Это полностью решает проблему ограничений NTFS Junctions и обеспечивает корректную работу команд СУБД. Разберем этот процесс по шагам:

  1. Настройка таргета на хранилище: На стороне вашего сетевого хранилища (NAS/SAN) создайте новый iSCSI Target (цель) и выделите под него необходимый объем дискового пространства (LUN). Настройте права доступа (ограничение по IP-адресу или по имени инициатора).
  2. Подключение инициатора в Windows: На сервере, где установлен PostgreSQL, откройте «Панель управления» -> «Администрирование» -> «Инициатор iSCSI» (iSCSI Initiator). Если служба инициатора не запущена, система предложит включить ее автоматический запуск — соглашаемся.
  3. Подключение диска: На вкладке «Быстрое подключение» введите IP-адрес вашего сетевого хранилища и нажмите кнопку «Быстрое подключение». Выберите обнаруженную цель и нажмите «Готово». Статус подключения должен измениться на «Подключено».
  4. Инициализация диска: Откройте стандартную оснастку Windows «Управление дисками» (diskmgmt.msc). Система обнаружит новый неинициализированный диск. Нажмите на него правой кнопкой мыши, выберите «Инициализировать диск», укажите стиль разделов GPT.
  5. Форматирование тома: Создайте простой том на этом диске, назначьте ему букву (например, E:\), выберите файловую систему NTFS и обязательно укажите размер кластера 64 КБ для оптимальной производительности СУБД.
  6. Настройка прав: Создайте на диске E:\ каталог (например, E:\pg_tablespaces\ts_1c) и в свойствах папки на вкладке «Безопасность» добавьте пользователя, под которым работает служба СУБД PostgreSQL, предоставив ему «Полный доступ».

Теперь вы можете спокойно создавать табличное пространство в pgAdmin или через консоль запросов, указав путь E:\pg_tablespaces\ts_1c. Ошибок не возникнет, так как для операционной системы и СУБД этот накопитель является локальным.

Решение 3. Использование символических ссылок (Symlinks) для работы с SMB-шарами (Альтернативный обходной путь)

Если развернуть iSCSI технически невозможно и вам крайне необходимо задействовать именно стандартную сетевую папку Windows (SMB), можно обойти ограничение СУБД, заменив стандартные Junction Points на символические ссылки файловой системы (Symbolic Links), которые умеют работать с сетевыми путями UNC.

Важное предупреждение: Данный метод является недокументированным обходным решением. Администратор берет на себя все риски потери целостности базы данных 1С при возникновении сетевых неполадок!

Рассмотрим по шагам, как реализовать этот метод:

  1. Настройка прав доступа на сетевом ресурсе. Предоставьте полный доступ (на уровне общего доступа и на уровне NTFS) к сетевой папке на удаленном сервере. Важно: права должны быть выданы либо конкретному доменному пользователю, под которым мы запустим службу СУБД, либо учетной записи компьютера СУБД в сети Active Directory (например, SERVER_PG$).
  2. Смена пользователя службы PostgreSQL. Откройте оснастку «Службы» (services.msc), найдите службу PostgreSQL. Откройте ее свойства, перейдите на вкладку «Вход в систему» и переключите переключатель с «Локальная система» на «С учетной записью». Укажите доменного пользователя, у которого есть доступ к сетевой папке, и введите его пароль. Перезапустите службу.
  3. Разрешение на создание символических ссылок. На сервере с СУБД откройте «Редактор локальной групповой политики» (gpedit.msc). Перейдите по пути: Конфигурация компьютера -> Конфигурация Windows -> Параметры безопасности -> Локальные политики -> Назначение прав пользователя -> Создание символических ссылок. Добавьте туда пользователя, от имени которого теперь работает служба PostgreSQL.
  4. Создание фиктивного табличного пространства. В СУБД PostgreSQL создайте табличное пространство, указав абсолютно любой пустой локальный каталог на сервере СУБД. Нам это нужно только для того, чтобы СУБД сгенерировала уникальный числовой идентификатор (OID) для этого пространства в папке pg_tblspc. CREATE TABLESPACE ger LOCATION 'C:\pg_dummy_dir';
  5. Остановка службы СУБД. Полностью остановите службу PostgreSQL через оснастку служб или команду net stop в командной строке.
  6. Подмена линка на сетевой путь. Перейдите в каталог данных СУБД C:\Program Files\PostgreSQL\...\data\pg_tblspc\. Вы увидите созданную точку соединения (Junction), которая выглядит как ярлык папки с числовым именем (например, 53730430). Удалите этот ярлык.
  7. Откройте командную строку от имени Администратора и создайте символическую ссылку вручную, используя флаг /D (создание символической ссылки на каталог, поддерживающей UNC), связав числовой OID с удаленным сервером:
    
    mklink /D "C:\Program Files\PostgreSQL\9.6.5-4.1C\data\pg_tblspc\53730430" "\\10.0.0.121\share\Program Files\PostgreSQL\data"
    
  8. Запуск СУБД и проверка. Запустите службу PostgreSQL. Теперь СУБД при обращении к табличному пространству через локальный путь автонаправления будет перенаправлять потоки ввода-вывода напрямую в сетевую папку по протоколу SMB. Попробуйте перенести базу данных 1С в это табличное пространство с помощью команды: ALTER DATABASE "ut-g" SET TABLESPACE ger;

Мы проанализировали причины возникновения ошибки недействительного аргумента при работе с сетевыми путями в PostgreSQL и разобрали три метода устранения неполадки. Настоятельно рекомендуем использовать Решение 1 или Решение 2 как наиболее отказоустойчивые и обеспечивающие сохранность ваших учетных данных 1С.

← На главную