MAATRIX / Блог / Предел размера одного файла: 2 ГБ, 4 ГБ или 16 ТБ — где споткнётся ваша система

Предел размера одного файла: 2 ГБ, 4 ГБ или 16 ТБ — где споткнётся ваша система

MAATRIX

Бэкап базы разросся до 6 ГБ и не копируется на старый NAS. Видео с камеры обрывается ровно на 4 ГБ. Дамп в панели управления загружается наполовину и падает с ошибкой без внятного текста. В каждом случае система технически исправна — просто где-то на пути файла стоит потолок, о котором никто не думал, пока в него не упёрлись. Разберём, какие пределы размера файла существуют на самом деле, на каком слое они прячутся и как их найти у себя за пять минут, а не методом проб и ошибок в проде.

Пять слоёв, на которых может стоять потолок

Когда файл «не заливается» или обрывается на ровном числе, ищите ограничение не в одном месте, а последовательно проходите по слоям — от процесса до конечного протокола:

  1. Формат и legacy-инструменты — старые 32-битные утилиты, форматы архивов, файловые системы с фиксированной шириной поля размера (FAT32).
  2. Современная файловая система — ext4, XFS и их теоретические (и практические) потолки на файл и на раздел.
  3. Лимит самого процесса в ОСulimit -f в шелле или LimitFSIZE в systemd-юните: про него забывают чаще всего.
  4. Лимит приложения — веб-сервер и рантайм (nginx, PHP, панель управления).
  5. Лимит протокола или API — у S3, почты, мессенджеров и внешних сервисов свои правила, никак не связанные с диском.

Дальше — по каждому слою с конкретикой: что именно ограничивает, как проверить у себя и где на практике об это спотыкаются.

32-битное наследие: 2 ГБ, 4 ГБ и FAT32, которые никуда не делись

Граница в 2 ГБ (2^31 байт) — это классический предел знакового 32-битного off_t: поле, которое хранит смещение внутри файла. Современные Linux-системы давно собраны с поддержкой Large File Support (LFS) и 64-битным off_t, так что для актуальных дистрибутивов (Ubuntu 24.04 и им подобных) эта проблема практически не встречается «в чистом виде». Но она возвращается косвенно — через старые бинарники, урезанные Docker-образы на базе древних дистрибутивов, самописные C-утилиты, собранные без LFS-флагов, или встроенные системы (камеры, роутеры, промышленные контроллеры) с урезанной прошивкой.

Граница в 4 ГБ (2^32 байт, если точнее — 4 294 967 295 байт) встречается чаще и в более неожиданных местах:

  • FAT32 физически не может хранить файл больше 4 ГиБ минус 1 байт — это жёстко зашито в формат таблицы размещения файлов. Если видеорегистратор, экшн-камера или старый NAS форматирует карту/диск в FAT32, длинная запись просто разрежется на куски по 4 ГБ автоматически (это штатное поведение прошивки), а если куда-то копируется уже готовый файл больше 4 ГБ — копирование оборвётся с ошибкой «файл слишком велик».
  • Старый формат tar (ustar) хранит размер файла в поле из 11 восьмеричных цифр, что даёт потолок около 8 ГиБ на один файл внутри архива. Современный GNU tar по умолчанию использует расширенные заголовки (GNU/pax-формат) и от этой границы не страдает, но если архив создавался с явным --format=ustar или древним tar на legacy-системе — можно получить битый архив на большом файле.
  • MyISAM-таблицы MySQL исторически ограничивались 4 ГБ на файл таблицы, если не были явно заданы параметры MAX_ROWS/AVG_ROW_LENGTH при создании и ОС не поддерживала большие файлы. У современного InnoDB (дефолтный движок уже много лет) такой жёсткой границы нет — там свои, гораздо более высокие потолки на табличное пространство.

Практический вывод: если в цепочке передачи данных где-то участвует карта памяти, старый USB-накопитель, самодельный NAS на базе роутерной прошивки или архив в формате ustar — проверьте формат явно, а не полагайтесь на «это же просто диск».

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Файловые системы: ext4, XFS и разница между теорией и практикой

На современных серверных ФС потолок размера файла — это давно не та проблема, с которой реально сталкиваются. Но полезно понимать порядок цифр, чтобы не тратить время на панику там, где предел заведомо недостижим при обычной нагрузке.

Файловая системаМаксимальный размер файла (по документации)Максимальный размер раздела
FAT324 ГиБ − 1 байт2 ТиБ (зависит от размера кластера)
ext4до 16 ТиБ при блоке 4 КБ (зависит от параметров mkfs)теоретически до 1 ЭиБ, практически определяется утилитами и ядром
XFSдо 8 ЭиБдо 8 ЭиБ
NTFSдо 16 ТиБ штатно, больше — при особых настройкахдесятки петабайт

Это ориентировочные цифры из документации самих файловых систем — точное значение для конкретного раздела зависит от размера блока, версии mkfs и параметров, с которыми раздел создавался, поэтому не берите их как гарантию, а проверяйте на месте. Практический предел почти всегда упирается не в файловую систему, а в физический размер тома, RAID-конфигурацию или лимиты гипервизора — ФС здесь редко становится узким местом первой.

Проверить тип и параметры своей файловой системы:

# тип ФС на смонтированном разделе
findmnt -T /var/lib/data

# блок и базовые параметры ext4
sudo dumpe2fs -h /dev/sdb1 | grep -E "Block size|Filesystem features"

# параметры XFS
sudo xfs_info /var/lib/data

Если вы ещё выбираете файловую систему под новый сервер — это отдельная тема, разобранная подробно в статье про выбор файловой системы ext4 vs XFS: для большинства сценариев разница на практике меньше, чем кажется, и предел размера файла в этом выборе почти никогда не решающий фактор.

Лимит процесса в ОС: забытый `ulimit -f`

Даже если файловая система пропускает файл любого разумного размера, процесс, который его пишет, может упереться в собственный лимит, заданный операционной системой. Это отдельный, часто забываемый слой — многие ищут проблему в диске или в приложении, а она в лимитах процесса.

# текущий лимит на размер файла для процесса (в блоках по 512 байт, "unlimited" — без ограничения)
ulimit -f

# для systemd-сервиса — смотрите LimitFSIZE в юните
systemctl show nginx.service | grep LimitFSIZE

# и в /etc/security/limits.conf, если лимиты выставлены через PAM
grep -i fsize /etc/security/limits.conf

По умолчанию на большинстве современных дистрибутивов этот лимит не задан (unlimited), но он может быть выставлен вручную в limits.conf, в systemd-юните конкретного сервиса или унаследован от родительского процесса (например, cron-задачи, запущенной от пользователя с ограничением). Если процесс резервного копирования или экспорта базы обрывается на подозрительно круглом числе гигабайт без ошибки файловой системы — это первое место для проверки.

Приложение и веб-сервер: nginx, PHP и лимиты аплоада

Даже когда диск и ОС не против, файл может не пройти через прикладной слой — веб-сервер и рантайм приложения. Это самый частый источник «загрузка обрывается на середине» для файлов, которые передаются через HTTP (панели управления, формы загрузки, API-эндпоинты).

nginx по умолчанию ограничивает тело запроса значением client_max_body_size 1m — то есть один мегабайт, если директива явно не переопределена. Для загрузки чего-то крупнее нужно явно поднять лимит в нужном контексте (http, server или location):

server {
    client_max_body_size 2G;
    ...
}

Проверить, какое значение реально применяется (с учётом всех include и переопределений по location):

sudo nginx -T | grep -i client_max_body_size

PHP ограничивает загрузку файлов сразу двумя параметрами в php.ini, и оба надо согласовать между собой:

upload_max_filesize = 2G
post_max_size = 2G
memory_limit = 2G

Частая ошибка — поднять только upload_max_filesize, забыв про post_max_size. Так как размер тела POST-запроса должен быть не меньше максимального размера файла, при рассинхроне PHP молча обрежет или отклонит загрузку — без внятной ошибки на стороне пользователя, только пустой $_FILES на стороне скрипта. memory_limit тоже должен быть не меньше, если файл обрабатывается в памяти, а не потоково.

php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"

То же самое касается других рантаймов и панелей: у большинства веб-панелей управления (для загрузки файлов через файловый менеджер) есть собственный лимит поверх лимитов nginx/PHP, и его тоже стоит проверять отдельно — иначе можно долго чинить конфиг веб-сервера, который на самом деле ни при чём. Похожая история с промежуточными прокси: в статье о том, как прокси резал тело запроса на одном мегабайте, разобран случай, когда лимит стоял не в приложении и не в веб-сервере, а в обратном прокси между ними — и найти его удалось только последовательной проверкой каждого звена цепочки.

Протоколы и внешние API: лимит не в диске, а в контракте сервиса

Отдельный класс ограничений — это не про диск и не про сервер вообще, а про правила конкретного протокола или внешнего сервиса, к которому вы обращаетесь. Эти лимиты нельзя обойти настройкой своего сервера — их можно только учитывать при проектировании потока данных.

  • Объектные хранилища, совместимые с S3-протоколом, обычно ограничивают одну операцию PUT объектом в единицы гигабайт (у AWS S3, например, это 5 ГиБ на один PUT) — для файлов крупнее используется multipart upload, где файл режется на части и загружается по кускам с последующей сборкой на стороне хранилища. Если вы поднимаете собственное S3-совместимое хранилище, конкретные лимиты и поддержку multipart стоит уточнять в документации выбранного решения — они не универсальны.
  • Почтовые сервисы ограничивают размер вложения, и лимит обычно на уровне десятков мегабайт — большие дампы или архивы почтой лучше не гонять в принципе, а передавать ссылкой на файл в хранилище.
  • API мессенджеров и ботов задают собственные потолки на файл в зависимости от типа отправки и типа аккаунта — это регулярно меняющиеся значения, которые надо смотреть в актуальной документации конкретного API на момент интеграции, а не закладывать в код по памяти.
  • Протоколы синхронизации и передачи (rsync, scp, sftp) сами по себе почти не имеют собственных пределов на размер файла — они ограничены нижележащими слоями (ФС на обоих концах, ulimit процесса), но зато чувствительны к обрыву соединения на длинной передаче: для действительно больших файлов важнее не столько лимит, сколько возможность докачки (rsync --partial, scp без резюма — это его слабое место).

Разница между слоем 2–4 (диск, ОС, приложение) и слоем 5 (протокол/API) принципиальна: первые вы контролируете и можете перенастроить на своём сервере, вторые — заданы снаружи, и единственный способ с ними работать — знать их заранее и проектировать передачу файлов с учётом дробления, а не упираться в отказ уже на проде.

Где это реально бьёт на практике: бэкапы, видео, дампы БД

Собрав всё вместе, вот конкретные сценарии, где предел размера файла проявляется чаще всего:

Резервное копирование. Бэкап базы или полного диска, упакованный в один архив, со временем перерастает 4 ГБ, потом 10, потом 50 — и первый, кто на это реагирует, обычно не файловая система сервера (там всё в порядке), а место назначения бэкапа: старый NAS с FAT32-разделом, внешний диск, отформатированный давно и не под линуксовую нагрузку, или скрипт передачи через инструмент с собственным лимитом. Отдельная и более тонкая проблема — не сам объём файла, а скорость его передачи по каналу с учётом шифрования; она разобрана в статье про предел скорости бэкапа: диск, шифрование, канал. Если бэкап делается без остановки сервиса, у него есть свои нюансы согласованности — они раскрыты в материале про бэкап баз данных без остановки.

Видео и медиафайлы. Необработанное 4K-видео с длинной записи легко превышает 4 ГБ за один файл — и если исходная запись велась на карту с FAT32 (типично для многих камер и регистраторов), она физически придёт кусками по 4 ГБ, которые потом нужно склеивать программно (ffmpeg concat или аналог), а не считать битыми файлами. Дальше при заливке смонтированного ролика через веб-интерфейс тот же файл может упереться уже в client_max_body_size или upload_max_filesize — это два разных предела на разных этапах одного и того же файла.

Дампы баз данных. mysqldump или pg_dump в один файл на активной базе за несколько лет легко вырастает до десятков гигабайт. Сам дамп на диске сервера — не проблема (ext4/XFS выдержат), проблема начинается при попытке скачать его через панель управления (лимит приложения), отправить по почте коллеге (лимит вложения) или загрузить в объектное хранилище одним PUT-запросом (лимит протокола). Решение обычно одно и то же на всех трёх фронтах: сжимать дамп (gzip/zstd, что снижает объём в разы) и/или резать его на части (split для файла, --single-transaction и потабличный экспорт для самого дампа), а не пытаться поднимать лимиты бесконечно под один растущий файл.

Как быстро проверить все слои у себя

Собранная в одну последовательность, диагностика выглядит так:

# 1. Формат и ФС места назначения
findmnt -T /path/to/target

# 2. Лимит процесса в ОС
ulimit -f
systemctl show <service>.service | grep LimitFSIZE

# 3. Лимит веб-сервера (если файл идёт через HTTP)
sudo nginx -T | grep -i client_max_body_size

# 4. Лимит рантайма приложения
php -i | grep -E "upload_max_filesize|post_max_size"

# 5. Свободное место и inode (частый спутник проблемы, не путать с пределом размера)
df -h /path/to/target
df -i /path/to/target

Проверяйте по порядку от диска к приложению — тогда легко отличить «файл физически не помещается» от «файл упёрся в настройку, которую можно поднять одной строкой в конфиге».

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему видео с камеры разбивается ровно на 4 ГБ?

Почти всегда это FAT32 на карте памяти — формат физически не хранит файл больше 4 ГиБ минус 1 байт, и прошивка камеры автоматически режет запись на части при достижении этой границы.

Ext4 или XFS — у кого потолок на файл выше?

По документации у XFS теоретический предел выше (до 8 ЭиБ против ~16 ТиБ у ext4 при стандартных параметрах), но для подавляющего большинства серверных сценариев обе ФС дают заведомо больше, чем реально нужно — выбор между ними чаще определяется другими факторами, а не пределом размера файла.

Загрузка файла в панели управления обрывается без ошибки — с чего начать?

С проверки цепочки в порядке: ulimit -f процесса → client_max_body_size в nginx → upload_max_filesize/post_max_size в PHP → собственный лимит самой панели. Обрыв без текста ошибки чаще всего означает, что оборвал именно веб-сервер или прокси, а не приложение.

Можно ли обойти лимит S3-совместимого хранилища на один PUT-запрос?

Да, для этого существует multipart upload — файл делится на части, каждая загружается отдельным запросом, хранилище собирает их в один объект. Это стандартный механизм, поддерживаемый большинством S3-совместимых решений, но детали (максимальное число частей, минимальный размер части) стоит смотреть в документации конкретного хранилища.

Стоит ли поднимать лимиты nginx и PHP «с запасом», чтобы не возвращаться к этому вопросу?

Разумный запас — да, но без фанатизма: слишком большой client_max_body_size при незащищённом эндпоинте — это ещё и вектor для DoS через отправку огромных тел запроса. Ставьте лимит под реальный максимальный размер ожидаемого файла плюс небольшой запас, а не «на всякий случай побольше».

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →