--- title: "创建新的 Translog 文件失败 - 如何解决此 Elasticsearch 异常" date: 2026-04-04 lastmod: 2026-04-04 description: "failed to create new translog file 表示 Elasticsearch 在切换或初始化 translog writer 时写入底层文件失败,重点应检查 shard 数据路径与磁盘 I/O。" tags: ["translog", "engine", "TranslogException", "磁盘空间", "文件写入", "分片恢复"] summary: "适用版本: 7.17-8.9 1. 错误异常的基本描述 # failed to create new translog file 表示 Elasticsearch 在创建新的 translog writer 文件时抛出了 IOException,随后被包装成 TranslogException。该异常发生在写入链路的最底层——translog 持久化阶段,意味着索引操作无法安全地写入事务日志,通常会直接影响分片的可写性和恢复能力。 常见现象 # 索引写入请求失败,返回 500 或 429 状态码,具体取决于是否触发了熔断或重试逻辑。 分片状态可能变为 RED 或 YELLOW,尤其在分片恢复、滚动重启或磁盘压力较大的场景下。 节点日志中会出现 TranslogException: failed to create new translog file 异常,并伴随 IOException 原因链。 如果问题持续存在,可能会导致分片无法分配、索引无法打开,甚至触发索引级别的只读保护。 典型报错与异常栈 # 该异常在日志中通常表现为以下形式: org.elasticsearch.index.translog.TranslogException: failed to create new translog file Caused by: java.io.IOException: No space left on device at java.io.FileOutputStream.open0(Native Method) at java." --- > **适用版本:** 7.17-8.9 ## 1. 错误异常的基本描述 `failed to create new translog file` 表示 Elasticsearch 在创建新的 translog writer 文件时抛出了 `IOException`,随后被包装成 `TranslogException`。该异常发生在写入链路的最底层——translog 持久化阶段,意味着索引操作无法安全地写入事务日志,通常会直接影响分片的可写性和恢复能力。 ### 常见现象 - 索引写入请求失败,返回 `500` 或 `429` 状态码,具体取决于是否触发了熔断或重试逻辑。 - 分片状态可能变为 `RED` 或 `YELLOW`,尤其在分片恢复、滚动重启或磁盘压力较大的场景下。 - 节点日志中会出现 `TranslogException: failed to create new translog file` 异常,并伴随 `IOException` 原因链。 - 如果问题持续存在,可能会导致分片无法分配、索引无法打开,甚至触发索引级别的只读保护。 ### 典型报错与异常栈 该异常在日志中通常表现为以下形式: ```text org.elasticsearch.index.translog.TranslogException: failed to create new translog file Caused by: java.io.IOException: No space left on device at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at org.elasticsearch.index.translog.Translog.createWriter(Translog.java:xxx) ``` 或: ```text TranslogException[failed to create new translog file] Caused by: java.nio.file.AccessDeniedException: /var/lib/elasticsearch/nodes/0/indices/xxx/0/translog/translog-xxx.tlog ``` ## 2. 为什么会发生这个错误 Translog(事务日志)是 Elasticsearch 保证数据可靠性的核心组件。每次索引操作(写入、更新、删除)在写入 Lucene 内存缓冲之前,都会先被记录到 translog 中。当 translog 文件大小达到阈值(默认 512MB)或发生 flush 操作时,Elasticsearch 会创建一个新的 translog 文件来继续接收写入。 如果在创建新 translog 文件的过程中,底层文件系统操作失败,就会抛出此异常。常见原因包括: - **磁盘空间不足**:数据分区使用率接近 100%,文件系统无法分配新的 inode 或数据块。 - **磁盘 inode 耗尽**:即使磁盘空间尚有剩余,但 inode 数量已用完,同样无法创建新文件。 - **文件权限异常**:Elasticsearch 进程对分片数据目录(`$ES_PATH_DATA/nodes/0/indices/`)没有写权限,常见于目录被手动修改权限或迁移后未正确授权。 - **文件系统只读挂载**:磁盘出现 I/O 错误后被系统自动重新挂载为只读模式(`ro`),导致所有写操作失败。 - **文件句柄耗尽**:操作系统级别的文件描述符(file descriptor)达到上限,无法打开新文件。 - **磁盘硬件故障或 I/O 抖动**:底层存储出现坏道、I/O 超时或存储驱动异常,导致文件创建操作失败。 - **分片目录损坏**:分片数据目录被外部进程意外修改或删除,导致 translog 目录结构不完整。 ## 3. 如何排查这个异常 建议按照"先确认影响范围,再定位根因"的顺序排查: 1. **确认异常影响范围**:检查是个别分片报错,还是整个节点甚至多个节点同时出现。单个分片异常往往指向目录权限或局部磁盘问题;多节点同时报错则更可能是存储系统层面的问题。 2. **检查磁盘空间与 inode**:在节点上执行 `df -h` 和 `df -i`,确认数据分区使用率是否超过 90%,以及 inode 是否耗尽。 3. **检查文件系统挂载状态**:执行 `mount | grep ` 确认数据目录所在分区是否为读写模式(`rw`),而非只读(`ro`)。 4. **检查 Elasticsearch 进程权限**:确认 `$ES_PATH_DATA` 目录及其子目录的所有者和权限是否正确,Elasticsearch 进程用户是否拥有写权限。 5. **检查文件句柄限制**:查看 Elasticsearch 日志中是否有 `too many open files` 相关报错,并对比 `ulimit -n` 的当前值和配置值。 6. **查看系统日志**:检查 `/var/log/syslog`、`dmesg` 或硬件监控平台,确认是否有磁盘 I/O 错误、文件系统报错或存储链路告警。 7. **结合时间窗口分析**:确认异常发生前后是否有磁盘迁移、节点重启、索引删除或操作系统补丁变更等操作。 ### 排查时需要注意的问题 - 不要只关注 translog 报错本身,磁盘问题往往会同时触发多种异常(如 `engine 启动失败`、`translog 损坏`、`segment 文件写入失败` 等),需要综合研判。 - 如果节点已被标记为磁盘水位超限(`high disk watermark`),Elasticsearch 会自动将该节点上的分片迁走,此时 translog 创建失败可能是迁移过程中的连带问题。 - 在容器化部署(Docker/K8s)场景下,还需确认宿主机磁盘和容器存储卷的映射关系是否正确,以及是否有存储卷容量限制(PVC quota)。 ## 4. 如何解决这个错误 ### 常用修复思路 - **磁盘空间不足**:清理过期数据、删除不需要的索引、扩容磁盘,或临时调高磁盘水位线(`cluster.routing.allocation.disk.watermark`)以恢复写入。 - **inode 耗尽**:查找并清理大量小文件(常见于 translog 或 segment 文件堆积),必要时重新格式化文件系统时指定更大的 inode 数量。 - **权限问题**:修正数据目录权限,例如执行 `chown -R elasticsearch:elasticsearch $ES_PATH_DATA` 和 `chmod -R 750 $ES_PATH_DATA`。 - **文件系统只读**:先排查磁盘硬件健康状态,确认无硬件故障后,尝试重新以读写模式挂载分区:`mount -o remount,rw `。 - **文件句柄耗尽**:修改系统限制,在 `/etc/security/limits.conf` 中增加 `elasticsearch soft nofile 65536` 和 `elasticsearch hard nofile 65536`,然后重启 Elasticsearch。 - **分片目录损坏**:如果确认目录结构损坏且无法修复,可以考虑从副本分片恢复,或通过快照(snapshot)重建索引。 ### 紧急恢复步骤 如果业务写入受到严重影响,可以按以下顺序快速止血: ```bash # 1. 临时关闭索引的只读保护(仅在确认磁盘问题已修复后执行) PUT //_settings { "index.blocks.read_only_allow_delete": null } # 2. 如果磁盘空间紧张,临时调高磁盘水位线(恢复后记得改回) PUT _cluster/settings { "transient": { "cluster.routing.allocation.disk.watermark.low": "90%", "cluster.routing.allocation.disk.watermark.high": "95%" } } # 3. 尝试手动分配因 translog 问题而未被分配的分片 POST /_cluster/reroute?retry_failed=true ``` ### 后续注意事项与推荐建议 - 为磁盘使用率、inode 使用率、文件句柄数和 I/O 延迟设置监控告警,在问题影响业务之前提前介入。 - 定期清理过期索引和旧的 translog 文件,避免磁盘空间被缓慢耗尽。 - 对关键索引保持至少一个副本,确保单节点磁盘故障时可以快速从副本恢复。 - 定期备份数据到远程快照仓库,确保极端情况下可以从快照恢复,而不是依赖可能已损坏的本地 translog。 ### 借助 INFINI 产品提升排障效率 - [INFINI Console](https://docs.infinilabs.com/console/main/) 适合查看集群健康度、节点磁盘使用率、分片分配状态和异常趋势,帮助快速判断 translog 异常是局部磁盘问题还是系统性问题。 - [INFINI Gateway](https://docs.infinilabs.com/gateway/main/) 适合部署在 Elasticsearch 前面做请求观测、限流和熔断,在磁盘异常期间减少写入压力,避免更多 translog 相关错误被连锁触发。 - 建议将磁盘告警、分片未分配事件和 translog 异常日志统一接入监控面板,缩短从"发现问题"到"定位根因"的时间。 ## 5. 小结 `failed to create new translog file` 的本质是 translog 新文件创建失败,根因几乎总是落在磁盘、文件系统或操作系统层面的资源限制上,而不是 Elasticsearch 本身的代码缺陷。排查时应优先关注分片本地目录的可写性、磁盘 I/O 健康状态以及操作系统资源限制,而不是请求参数或索引 mapping。只要把磁盘监控、权限管理和容量规划固定下来,这类异常可以在很大程度上被提前预防。 ## 相关错误 - [创建引擎失败](/knowledge-base/elasticsearch_error/failed-to-create-engine-how-to-solve-this-elasticsearch-exception/) - [创建本地检查点跟踪器失败](/knowledge-base/elasticsearch_error/failed-to-create-local-checkpoint-tracker-how-to-solve-this-elasticsearch-exception/) - [创建空 Store 失败](/knowledge-base/elasticsearch_error/failed-to-create-empty-store-how-to-solve-this-elasticsearch-exception/) - [translog 损坏](/knowledge-base/elasticsearch_error/translog-is-corrupted-how-to-solve-this-elasticsearch-exception/) - [索引目录被锁定](/knowledge-base/elasticsearch_error/index-directory-is-locked-how-to-solve-this-elasticsearch-exception/) ## 附:日志上下文 下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题: ```java bigArrays; diskIoBufferPool; operationListener ); } catch (final IOException e) { throw new TranslogException(shardId; "failed to create new translog file"; e); } return newWriter; } ```