> For the complete documentation index, see [llms.txt](https://ayakaleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayakaleaf-pro.ayaka.space/on-premises/vi/ho-tro/support-guides/v5.5.7-migration-binary-files-migration.md).

# (Di chuyển v5.5.7) Di chuyển tệp nhị phân

## Di chuyển tệp nhị phân

Phiên bản lớn sắp tới `6.0` bản phát hành của Server Pro và Community Edition sẽ giảm một nửa mức sử dụng lưu trữ của các tệp nhị phân. Một quá trình di chuyển trực tuyến được bao gồm trong phiên bản `5.5.7` , cho phép thời gian gián đoạn ở mức tối thiểu trong quá trình nâng cấp.

Kể từ Server Pro `4.x`, các tệp nhị phân được lưu trữ hai lần: trong bộ lưu trữ tệp đang hoạt động ở "filestore" và trong hệ thống lịch sử đầy đủ của dự án. Từ nay về sau, mỗi tệp sẽ chỉ được lưu một bản sao trong hệ thống lịch sử đầy đủ của dự án.

Quá trình di chuyển sang hệ thống lưu trữ hợp nhất gồm hai phần: một cờ mới để kiểm soát giai đoạn di chuyển và một script xử lý tất cả các dự án đang hoạt động và đã xóa mềm.

Các giai đoạn:

* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=0` (mặc định), các tệp được đọc và ghi vào filestore. Các tệp được ghi vào lịch sử một cách không đồng bộ.
* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1` , các tệp được đọc từ lịch sử với cơ chế dự phòng sang filestore và được ghi vào cả filestore lẫn lịch sử. Hạ cấp xuống `OVERLEAF_FILESTORE_MIGRATION_LEVEL=0` là khả thi.
* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=2` các tệp chỉ được đọc và ghi vào lịch sử. Hạ cấp xuống `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1` là không thể, trừ khi nó được thực hiện "ngoại tuyến".

Khi lưu trữ dữ liệu trong [S3](https://docs.overleaf.com/on-premises/configuration/overleaf-toolkit/s3) và sử dụng các tài khoản dịch vụ riêng cho filestore (`OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID`) và history (`OVERLEAF_HISTORY_S3_ACCESS_KEY_ID`): Vui lòng cấp cho người dùng filestore quyền đọc vào bucket lịch sử đối với các blob `OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET` . Dịch vụ filestore sẽ đảm nhiệm việc đọc từ dịch vụ biên dịch từ nay về sau.

{% hint style="warning" %}
Khuyến nghị mạnh mẽ là nên thực hiện di chuyển tệp nhị phân trong môi trường không phải sản xuất/sandbox trước.
{% endhint %}

{% hint style="success" %}
Giấy phép Server Pro tiêu chuẩn cho phép bạn chạy ứng dụng trong môi trường sản xuất cũng như một môi trường không phải sản xuất/sandbox; chúng tôi khuyến nghị mạnh mẽ bạn thiết lập một môi trường không phải sản xuất để thử nghiệm.
{% endhint %}

{% hint style="info" %}
Nếu bạn nâng cấp lên phiên bản Server Pro/CE `6.0` và sau đó quyết định hạ cấp xuống phiên bản cũ hơn, thì bạn nên khôi phục từ bản sao lưu hệ thống đầy đủ.
{% endhint %}

### Quy trình di chuyển

{% stepper %}
{% step %}

#### Tạo bản sao lưu

Tạo một bản [sao lưu](https://docs.overleaf.com/on-premises/maintenance/data-and-backups#performing-a-consistent-backup) toàn bộ của phiên bản của bạn với một ảnh chụp nhất quán của **mongo**, **redis** và **sharelatex** các thư mục.
{% endstep %}

{% step %}

#### Cập nhật

**Toolkit:** Dùng `$ bin/upgrade` script để nâng cấp **toolkit** lên phiên bản mới nhất. Khi được hỏi, đừng **không** xác nhận lời nhắc **Nâng cấp** image? — thay vào đó, hãy chỉnh sửa thủ công **config/version** tệp và đặt giá trị thành `5.5.7`.

**docker-compose.yml cũ:** Cập nhật phiên bản của `sharelatex` dịch vụ thành `5.5.7`.
{% endstep %}

{% step %}

#### Ước tính số lượng dự án bị ảnh hưởng

{% code overflow="wrap" %}

```bash
# Người dùng Overleaf Toolkit:
$ bin/docker-compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --report"

# Người dùng docker-compose.yml cũ:
$ docker compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --report"
```

{% endcode %}

Ví dụ đầu ra:

{% code fullWidth="false" %}

```
Trạng thái hiện tại:
- Tổng số dự án: 10
- Tổng số dự án đã xóa: 5
Đang lấy mẫu 1000 dự án để ước tính tiến độ...
Số liệu mẫu cho các dự án:
- Số dự án được lấy mẫu: 9 (90% tổng số dự án)
- Số dự án được lấy mẫu có đủ tất cả các hash: 5
- Tỷ lệ dự án cần bổ sung hash: 44% (ước tính)
- Các dự án được lấy mẫu có 11 tệp cần được kiểm tra đối chiếu với hệ thống lịch sử đầy đủ của dự án.
- Các dự án được lấy mẫu có 3 tệp cần được tải lên hệ thống lịch sử đầy đủ của dự án (ước tính 27% tổng số tệp).
Số liệu mẫu cho các dự án đã xóa:
- Số dự án đã xóa được lấy mẫu: 4 (80% tổng số dự án đã xóa)
- Số dự án đã xóa được lấy mẫu có đủ tất cả các hash: 3
- Tỷ lệ dự án đã xóa cần bổ sung hash: 25% (ước tính)
- Các dự án đã xóa được lấy mẫu có 2 tệp cần được kiểm tra đối chiếu với hệ thống lịch sử đầy đủ của dự án.
- Các dự án đã xóa được lấy mẫu có 1 tệp cần được tải lên hệ thống lịch sử đầy đủ của dự án (ước tính 50% tổng số tệp).
```

{% endcode %}
{% endstep %}

{% step %}

#### Xả hàng đợi lịch sử dự án

{% code overflow="wrap" %}

```bash
# Người dùng Overleaf Toolkit:
$ bin/docker-compose exec sharelatex /overleaf/bin/flush-history-queues

# Người dùng docker-compose.yml cũ:
$ docker compose exec sharelatex /overleaf/bin/flush-history-queues
```

{% endcode %}

Lặp lại việc xả cho đến khi tất cả các dự án đã được xả (`"project_ids":0`).

```
found projects {"project_ids":0,"limit":100000,"ts":"2025-09-01T10:35:33.353Z"}
total {"succeededProjects":0,"failedProjects":0}
```

{% hint style="danger" %}
Trong trường hợp "failedProjects" không bằng 0, vui lòng liên hệ hỗ trợ và đừng tiếp tục quá trình di chuyển tệp nhị phân.
{% endhint %}
{% endstep %}

{% step %}

#### Chuyển giai đoạn di chuyển sang 1

Toolkit: Đặt `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1` trong `config/variables.env`.

docker-compose.yml cũ: Đặt `OVERLEAF_FILESTORE_MIGRATION_LEVEL: '1'` trong `môi trường` phần của `sharelatex` dịch vụ.
{% endstep %}

{% step %}

#### Áp dụng thay đổi cấu hình và khởi động phiên bản

Toolkit: `bin/up -d`

docker-compose.yml cũ: `docker compose up -d`
{% endstep %}

{% step %}

#### Xác minh quyền truy cập vào tệp nhị phân

Mở một dự án trong trình soạn thảo Overleaf trên trình duyệt và chọn một tệp nhị phân, chẳng hạn như hình ảnh.
{% endstep %}

{% step %}

#### Chạy script di chuyển

{% code overflow="wrap" %}

```bash
# Người dùng Overleaf Toolkit:
$ bin/docker-compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --all"

# Người dùng docker-compose.yml cũ:
$ docker compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --all"
```

{% endcode %}

{% hint style="danger" %}
Nếu bạn đang [lưu log](https://docs.overleaf.com/on-premises/configuration/overleaf-toolkit/logging#persisting-logs) tệp bên ngoài **sharelatex** container, hãy đảm bảo chủ sở hữu của thư mục logs được đặt thành `www-data` người dùng (uid=33) để tệp log đầu ra có thể được ghi.
{% endhint %}

Kết quả đầu ra sẽ trông như sau:

```bash
Set UV_THREADPOOL_SIZE=16
{"name":"default","hostname":"c25e9faaeb53","pid":971,"level":30,"backend":"fs","msg":"Loading backend","time":"2025-07-25T15:00:58.166Z","v":0}
Đang ghi log vào /var/log/overleaf/file-migration-2025-07-25T15_00_58_199Z.log
Đang bắt đầu sao lưu tệp dự án...
Đã tải blob toàn cục: 0
Đang xử lý các dự án không bị xóa...
Đã xử lý 1 dự án, thời gian đã qua 0 giây
Đã xong cập nhật các dự án đang hoạt động
Đang xử lý các dự án đã xóa...
Bộ sưu tập deletedProjects dường như trống.

Đã xong cập nhật các dự án đã xóa
Xong.

```

Nếu quá trình di chuyển thành công, bạn sẽ nhận được mã thoát là `0`, và các dòng cuối cùng cho biết không có lỗi:

```bash
Xong.
```

Tệp log sẽ trông như thế này (dùng đường dẫn do script in ra):

{% code overflow="wrap" %}

```bash
$ docker cp sharelatex:/var/log/overleaf/file-migration-2025-07-25T15_00_58_199Z.log .
$ cat file-migration-2025-07-25T15_00_58_199Z.log
{"name":"file-migration","hostname":"c25e9faaeb53","pid":971,"level":30,"end":"68839a8f577b9f009d947b27 (2025-07-25T14:54:07.000Z)","msg":"actually completed batch","time":"2025-07-25T15:00:58.379Z","v":0}
{"name":"file-migration","hostname":"c25e9faaeb53","pid":971,"level":30,"time":"2025-07-25T15:00:58.383Z","LOGGING_IDENTIFIER":"4effa2000000000000000000","projects":1,"blobs":6,"filesWithHash":5,"filesWithoutHash":2,"filesDuplicated":0,"filesRetries":0,"filesFailed":0,"fileTreeUpdated":0,"badFileTrees":0,"globalBlobsCount":0,"globalBlobsEgress":0,"projectDeleted":0,"projectHardDeleted":0,"fileHardDeleted":0,"mongoUpdates":1,"readFromGCSCount":7,"readFromGCSIngress":28532,"writeToGCSCount":5,"writeToGCSEgress":300,"readFromGCSThroughputMiBPerSecond":0.14925639825786063,"eventLoop":{"idle":48.277844,"active":381.53244699971054,"utilization":0.8876763888372498},"diff":{"eventLoop":{"idle":48.223536,"active":134.04030200059555,"utilization":0.7354190687027976},"projects":1,"blobs":6,"filesWithHash":5,"filesWithoutHash":2,"filesDuplicated":0,"filesRetries":0,"filesFailed":0,"fileTreeUpdated":0,"badFileTrees":0,"globalBlobsCount":0,"globalBlobsEgress":0,"projectDeleted":0,"projectHardDeleted":0,"fileHardDeleted":0,"mongoUpdates":1,"readFromGCSCount":7,"readFromGCSIngress":28532,"writeToGCSCount":5,"writeToGCSEgress":300,"readFromGCSThroughputMiBPerSecond":0.14925639825786063},"deferredBatches":[],"msg":"file-migration stats","v":0}
```

{% endcode %}
{% endstep %}

{% step %}

#### Dừng phiên bản

Toolkit: `bin/stop sharelatex`

docker-compose.yml cũ: `docker compose stop sharelatex`
{% endstep %}

{% step %}

#### Làm cho các tệp cũ không thể truy cập được đối với ứng dụng

Bây giờ bạn có thể chuyển các tệp cũ sang lưu trữ phụ. Chúng tôi khuyên bạn nên giữ các tệp này một thời gian phòng khi sau này phát sinh sự cố.

{% code overflow="wrap" %}

```bash
# Người dùng Toolkit:
$ bin/docker-compose run --rm --entrypoint mv sharelatex --no-clobber --verbose /var/lib/overleaf/data/user_files /var/lib/overleaf/data/old_user_files

# Người dùng docker-compose.yml cũ:
# Chúng tôi giả định rằng bạn đang sử dụng bind-mount mặc định trong /var/lib/overleaf
$ docker compose run --rm --entrypoint mv sharelatex --no-clobber --verbose /var/lib/overleaf/data/user_files /var/lib/overleaf/data/old_user_files
# Trong trường hợp bạn đang sử dụng các bind-mount chọn lọc, bạn chỉ cần xóa bind-mount cho /var/lib/overleaf/data/user_files bên trong container.
```

{% endcode %}
{% endstep %}

{% step %}

#### Chuyển giai đoạn di chuyển sang 2

Toolkit: Đặt `OVERLEAF_FILESTORE_MIGRATION_LEVEL=2` trong `config/variables.env`.

docker-compose.yml cũ: Đặt `OVERLEAF_FILESTORE_MIGRATION_LEVEL: '2'` trong `môi trường` phần của `sharelatex` dịch vụ.
{% endstep %}

{% step %}

#### Áp dụng thay đổi cấu hình và khởi động phiên bản

Toolkit: `bin/up -d`

docker-compose.yml cũ: `docker compose up -d`
{% endstep %}

{% step %}

#### Xác minh quyền truy cập vào tệp nhị phân

Mở một dự án trong trình soạn thảo Overleaf trên trình duyệt và chọn một tệp nhị phân, chẳng hạn như hình ảnh.
{% endstep %}
{% endstepper %}

#### Di chuyển ngoại tuyến

Nếu bạn muốn ngăn người dùng đăng nhập trong khi script di chuyển tệp nhị phân đang chạy, vui lòng làm theo các bước sau:

* Đăng nhập vào phiên bản Overleaf của bạn bằng tài khoản quản trị viên
* Nhấp vào **Quản trị** nút và chọn **Quản lý trang**
* Nhấp vào **Mở/Đóng Trình soạn thảo** tab
* Nhấp vào **Đóng Trình soạn thảo** nút
* Nhấp vào **Ngắt kết nối tất cả người dùng** nút

Khi việc này đã được thực hiện, nếu có người dùng nào đang đăng nhập thì họ sẽ được chuyển hướng đến trang bảo trì, và bất kỳ người dùng mới nào truy cập trang đăng nhập sẽ thấy trang bảo trì và **sẽ không** có thể đăng nhập.

Bạn cần lặp lại các bước này khi khởi động lại phiên bản. Để mở lại trang web, chỉ cần khởi động lại phiên bản.

#### Di chuyển trực tuyến

Có thể chạy các script di chuyển trong khi ứng dụng vẫn đang chạy. Có một vài điểm cần lưu ý:

* Quá trình di chuyển rất tốn I/O, bạn nên theo dõi việc sử dụng tài nguyên trong khi script đang chạy.
* Với mức độ đồng thời xử lý cao, vòng lặp sự kiện trong `filestore` dịch vụ có thể bị chặn ở một số thời điểm, dẫn đến trải nghiệm người dùng giảm sút. Chúng tôi khuyên bạn nên bắt đầu với các giá trị mặc định của `--concurrency=10` và `--concurrent-batches=1` .
* Bạn có thể dừng script bất cứ lúc nào. Khi chạy lại, nó sẽ xác thực các dự án trước đó và bỏ qua các tệp đã được xử lý rồi. Điều này hữu ích trong trường hợp bạn muốn chạy quá trình di chuyển vào những giờ ít bận hơn (ví dụ: ban đêm).

Khuyến nghị của chúng tôi là đóng trang web và chạy quá trình di chuyển ngoại tuyến trong một cửa sổ bảo trì khi số lượng dự án của bạn dưới 1000 dự án (xem đầu ra của script di chuyển khi chạy với `--report`). Nếu số lượng dự án lớn, bạn có thể chạy script và theo dõi tiến độ, sau đó quyết định có tiếp tục chạy trực tuyến hay ngoại tuyến tùy theo trường hợp cụ thể của bạn.

#### Dọn dẹp dữ liệu tệp nhị phân cũ

Khi bạn đã hoàn tất quá trình di chuyển và xác minh rằng các dự án vẫn có thể truy cập tất cả các tệp của chúng, bạn có thể xóa bộ lưu trữ tệp cũ trong `/var/lib/overleaf/data/user_files`. Chúng tôi đặc biệt khuyên bạn nên giữ các tệp này một thời gian - bạn có thể làm cho chúng không thể truy cập được đối với ứng dụng bằng cách đổi tên thư mục trước.

### Khắc phục sự cố

Chúng tôi sẽ bổ sung hướng dẫn khắc phục sự cố ở đây. Xin lưu ý rằng mặc dù thông thường chúng tôi chỉ hỗ trợ khách hàng Server Pro, nhưng với bản chất của quá trình di chuyển này, chúng tôi cũng sẽ cố gắng hết sức để hỗ trợ khách hàng CE gặp sự cố cụ thể liên quan đến quá trình di chuyển tệp nhị phân.

Nếu script di chuyển tệp nhị phân thất bại (tức là thoát với lỗi hoặc in ra số dự án thất bại khác 0), vui lòng gửi các chi tiết sau cho đội hỗ trợ của chúng tôi qua email [support+filestoremigration@overleaf.com](mailto:support+filestoremigration@overleaf.com?subject=Binary%20file%20migration%20problem\&body=Instance%20Type%3A%20CE%20or%20Server%20Pro%20%28delete%20as%20appropriate%29%0A%0AInstallation%20Type%3A%20Overleaf%20toolkit%20or%20docker-compose.yml%20or%20other%20%28delete%20as%20appropriate%29%0A%0AScript%20output%3A%0A%0Abin%2Fdoctor%20output%20%28if%20using%20toolkit%29%3A%0A), nêu rõ:

Tiêu đề: Vấn đề di chuyển tệp nhị phân

Nội dung:

* Loại phiên bản: CE hoặc Server Pro (xóa phần không phù hợp)
* Loại cài đặt: Overleaf toolkit hoặc `docker-compose.yml` hoặc khác (xóa phần không phù hợp)
* Phiên bản: 5.5.x (toolkit: `$ cat config/version`)
* Kết quả đầu ra của script di chuyển (nên nằm trong container tại `/var/log/overleaf`)
* Báo cáo: (chạy script di chuyển với `--report`)
* Dự án đã xử lý: (theo lần chạy gần nhất của script)
* Thời lượng của quá trình di chuyển:
* `bin/doctor` kết quả đầu ra (khi dùng toolkit)
* Phiên bản Toolkit: `$ git rev-parse HEAD` (khi dùng Toolkit)

Hãy cân nhắc đính kèm các tệp log của `filestore` dịch vụ vào email. Bạn có thể tìm thấy nó tại `/var/log/overleaf/filestore.log` bên trong `sharelatex` container và xuất chúng như sau:

```bash
$ docker cp sharelatex:/var/log/overleaf/filestore.log .
# thay <timestamp> bằng dấu thời gian như script đã in ra
$ docker cp sharelatex:/var/log/overleaf/file-migration-<timestamp>.log .
```

Vui lòng xóa mọi thông tin nhạy cảm khỏi các tệp log trước khi đính kèm chúng.

#### Thiếu tệp

Các phiên bản Server Pro/CE cũ hơn đã tạo các mục file-tree trước khi việc tải lên của người dùng hoàn tất, điều này có thể khiến các tệp trông như bị thiếu khi một lần tải lên thất bại. Bạn có thể thấy một vài trường hợp như vậy được báo cáo là lỗi khi xử lý tất cả các file-tree.

Trong trường hợp số lượng tệp bị thiếu ít, hãy cân nhắc xem xét thủ công các trường hợp này và xóa chúng trong trình soạn thảo trên trình duyệt.

Trong trường hợp số lượng tệp bị thiếu nhiều, hãy cân nhắc liên hệ hỗ trợ, xem mẫu email ở trên.

#### Tìm các cây tệp bị lỗi

Quá trình di chuyển có thể thất bại đối với các dự án có cây tệp bị lỗi cấu trúc (ví dụ: tên tệp trống). Bạn có thể tìm danh sách các vấn đề này bằng `find_malformed_filetrees` script kiểm tra tất cả dự án trong cơ sở dữ liệu:

{% code overflow="wrap" %}

```bash
$ bin/docker-compose exec sharelatex /bin/bash -c "cd /overleaf/services/web && /sbin/setuser www-data node scripts/find_malformed_filetrees.mjs > /tmp/malformed-file-trees.json"
```

{% endcode %}

Để sửa các đường dẫn không hợp lệ, hãy dùng `fix_malformed_filetree` script, chạy lệnh một lần cho mỗi đường dẫn lỗi:

{% code overflow="wrap" %}

```bash
$ bin/docker-compose exec sharelatex /bin/bash -c "cd /overleaf/services/web && /sbin/setuser www-data node scripts/fix_malformed_filetree.mjs --logs=/tmp/malformed-file-trees.json"
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ayakaleaf-pro.ayaka.space/on-premises/vi/ho-tro/support-guides/v5.5.7-migration-binary-files-migration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
