สำรอง นำออก และนำเข้า
ทุกสิ่งที่ Control Center คัดลอก ส่งต่อ หรือนำมาใช้ได้ พร้อมรูปร่างที่แน่นอนของอาร์ติแฟกต์ แต่ละชิ้น หากต้องการสำรองข้อมูลจริง ๆ ดู สำรองและกู้คืน ส่วนเหตุใดการเก็บข้อมูลถาวรจึง แยกแบบนี้ ดูเวิร์กสเปซและการแยกโดเมน
อาร์ติแฟกต์
หัวข้อที่มีชื่อว่า “อาร์ติแฟกต์”มีอาร์ติแฟกต์สำเนาฐานข้อมูลสามแบบ ซึ่งมีขอบเขตและนโยบายการลบต่างกัน
| อาร์ติแฟกต์ | เขียนโดย | รูปร่าง | ครอบคลุม |
|---|---|---|---|
| สแนปช็อตการติดตั้ง | server.backupNow |
ไดเรกทอรีที่ประทับเวลา | ทุกฐานข้อมูลบนการติดตั้ง |
| ข้อมูลสำรองของเวิร์กสเปซ | ไปป์ไลน์ Workspace backup |
ไดเรกทอรีที่ประทับเวลาซึ่งมี .db หนึ่งไฟล์ |
ฐานข้อมูลของเวิร์กสเปซหนึ่งตัว |
| การส่งออกเวิร์กสเปซ | workspace.export |
ไฟล์ .db ไฟล์เดียว |
ฐานข้อมูลของเวิร์กสเปซหนึ่งตัว |
ทั้งหมดเขียนด้วย VACUUM INTO ของ SQLite ซึ่งปลอดภัยกับฐานข้อมูล WAL ที่ใช้งานอยู่:
มันเปิดทรานแซกชันแบบอ่าน สร้างสำเนาที่จัดเรียงข้อมูลใหม่และสอดคล้องเชิงทรานแซกชัน
และไม่ต้องหยุดเซิร์ฟเวอร์เลย
โครงร่างของสแนปช็อต
หัวข้อที่มีชื่อว่า “โครงร่างของสแนปช็อต”<dataDir>/backups/2026-07-28T09-12-33-000Z/ manifest.json global.db <workspaceId>/workspace.db one directory per workspaceโครงร่างสะท้อนไดเรกทอรีข้อมูลที่ใช้งานอยู่แบบตรงทั้งหมด ซึ่งเป็นสิ่งที่ทำให้การกู้คืน
การติดตั้งเป็นการคัดลอกกลับ ไม่ใช่การแปลง ชื่อไดเรกทอรีคือเวลาประทับ UTC
โดยแทน : และ . ด้วย - จึงปลอดภัยกับระบบไฟล์บน Windows และเรียงตามเวลาได้
ด้วยการเทียบสตริงธรรมดา
ข้อมูลสำรองของเวิร์กสเปซตามกำหนดเวลาอยู่แยกกันที่
<dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db
โดยไม่มีแมนิเฟสต์หรือ global.db และไม่ใช่สแนปช็อตการติดตั้ง
ขั้นตอนการเก็บรักษาของไปป์ไลน์รายสัปดาห์ลบเฉพาะข้อมูลสำรองของเวิร์กสเปซตัวเอง
ที่เก่ากว่าอายุที่กำหนดไว้ (ค่าเริ่มต้น 30 วัน) เท่านั้น สแนปช็อตการติดตั้งที่สร้างด้วยมือ
จะไม่ถูกหมุนเวียนโดยขั้นตอนนั้นเลย server.listBackups แสดงเฉพาะสแนปช็อตการติดตั้ง
รวมถึงสแนปช็อตที่ไม่ครบด้วย
manifest.json
หัวข้อที่มีชื่อว่า “manifest.json”| ฟิลด์ | ชนิด | ความหมาย |
|---|---|---|
version |
int | เวอร์ชันรูปแบบของแมนิเฟสต์ ปัจจุบันคือ 1 |
created_at |
ISO-8601 UTC | เวลาที่ถ่ายสแนปช็อต |
global.file |
string | เป็น global.db เสมอ |
global.schema_version |
int | เวอร์ชันสคีมาของ GlobalDatabase ณ เวลาที่จับข้อมูล |
global.bytes |
int | ขนาดของ global.db ที่เขียนลงดิสก์ |
workspace_schema_version |
int | เวอร์ชันสคีมาของ WorkspaceDatabase ที่ไฟล์เวิร์กสเปซทุกไฟล์ใช้ร่วมกัน |
workspaces[] |
array | หนึ่งรายการต่อเวิร์กสเปซที่จับมา |
workspaces[].workspace_id |
string | เวิร์กสเปซที่ไฟล์นี้เก็บไว้ |
workspaces[].file |
string | พาธเทียบกับรากของสแนปช็อต <workspaceId>/workspace.db |
workspaces[].bytes |
int | ขนาดของไฟล์นั้น |
skipped_workspaces[] |
array of string | เวิร์กสเปซที่ข้อมูลสำรอง จับไม่ได้ |
เวิร์กสเปซจะถูกข้ามเมื่อมันถูกลงทะเบียนแต่ยังไม่เคยถูกเขียนเลย (จึงยังไม่มีไฟล์)
หรือเมื่อ VACUUM INTO ของมันล้มเหลว ไม่ว่ากรณีใด สแนปช็อตก็ยังเสร็จสมบูรณ์
และแมนิเฟสต์ระบุสิ่งที่ขาดหายไว้
ความครบถ้วน
หัวข้อที่มีชื่อว่า “ความครบถ้วน”server.listBackups รายงานแฟล็ก complete ต่อสแนปช็อตหนึ่งตัว โดยเป็น false เมื่อ
แมนิเฟสต์หายไปหรืออ่านไม่รู้เรื่อง เมื่อ global.db หายไป หรือเมื่อแมนิเฟสต์
ระบุชื่อไฟล์เวิร์กสเปซที่ไม่มีอยู่บนดิสก์
สแนปช็อตที่ไม่ครบยังคงถูกแสดง เพราะสแนปช็อตที่ผู้ดำเนินการมองไม่เห็นคือ
สแนปช็อตที่พวกเขาเชื่อว่ามีอยู่ เมื่ออ่านแมนิเฟสต์ไม่ได้ การแสดงรายการจะถอยไปใช้
โครงร่างเองและรายงานไฟล์ <workspaceId>/workspace.db ที่หาเจอ —
ไฟล์เหล่านั้นยังนำมาใช้ทีละไฟล์ผ่าน workspace.import ได้ แม้สแนปช็อต
ทั้งก้อนจะกู้คืนการติดตั้งไม่ได้ก็ตาม
สิ่งที่ข้อมูลสำรองไม่มี
หัวข้อที่มีชื่อว่า “สิ่งที่ข้อมูลสำรองไม่มี”อาร์ติแฟกต์ทั้งสองเป็นฐานข้อมูลเท่านั้น ไดเรกทอรีของเวิร์กสเปซเก็บมากกว่า ฐานข้อมูลของมัน และส่วนที่เหลือไม่ได้เดินทางไปด้วยเลย:
| พาธ | อยู่ในสแนปช็อต? | อยู่ในการส่งออกเวิร์กสเปซ? |
|---|---|---|
global.db |
ใช่ | ไม่ |
<workspaceId>/workspace.db |
ใช่ | ใช่ (มันคือไฟล์นั้น) |
<workspaceId>/blobs/ |
ไม่ | ไม่ |
<workspaceId>/skills/ |
ไม่ | ไม่ |
<workspaceId>/agents/ |
ไม่ | ไม่ |
<workspaceId>/chat_credentials/ |
ไม่ | ไม่ |
<workspaceId>/spaces/<spaceId>/ |
ไม่ | ไม่ |
<workspaceId>/pr_clones/ |
ไม่ | ไม่ |
secrets.json |
ไม่ | ไม่ |
models/ |
ไม่ | ไม่ |
meetings/<meetingId>/ |
ไม่ | ไม่ |
rigs/ |
ไม่ | ไม่ |
บางส่วนทิ้งได้ — spaces/ เก็บเวิร์กทรีแบบ copy-on-write ที่จัดเตรียมใหม่จากรีโป,
pr_clones/ เป็นแคช, models/ ดาวน์โหลดใหม่ได้, rigs/ เป็นสถานะของเครื่อง
บางส่วนทิ้งไม่ได้: blobs/ เก็บรูปที่วางเข้ามาซึ่งแถวในฐานข้อมูลชี้ไปหา, skills/
และ agents/ เก็บไฟล์ที่เอเจนต์ใช้รัน และ secrets.json เก็บคีย์จับคู่ทุกอัน
ข้อมูลรับรองของผู้ให้บริการ และการตั้งค่า SSO ทั้งหมดบนการติดตั้ง ดู
สำรองและกู้คืน
สำหรับวิธีครอบคลุมส่วนที่เหลือ
ปฏิบัติการ
หัวข้อที่มีชื่อว่า “ปฏิบัติการ”RPC สำหรับสำรองการติดตั้งและการส่งออก/นำเข้าเวิร์กสเปซใช้ได้เฉพาะ fullClient:
โทรศัพท์ที่จับคู่แล้วเรียกใช้ไม่ได้ ทั้งหมดไม่มีอยู่เลย — ไม่ใช่ถูกปฏิเสธ แต่หายไป
เชิงโครงสร้าง — บนเซิร์ฟเวอร์ที่ไม่ได้ต่อพอร์ตสำรองไว้ เช่นเซิร์ฟเวอร์สาธิต
| ปฏิบัติการ | ชนิด | ขอบเขต | บทบาทขั้นต่ำ | อาร์กิวเมนต์ | ส่งคืน |
|---|---|---|---|---|---|
server.backupNow |
กลายพันธุ์ | การติดตั้ง | เจ้าของ การติดตั้ง | ไม่มี | {ok, path} |
server.listBackups |
อ่าน | การติดตั้ง | เจ้าของ การติดตั้ง | ไม่มี | {backups: [...]} |
server.deleteBackup |
กลายพันธุ์ | การติดตั้ง | เจ้าของ การติดตั้ง | name |
{ok} |
workspace.export |
อ่าน | เวิร์กสเปซ | admin |
ไม่มี | {ok, path} |
workspace.import |
กลายพันธุ์ | เวิร์กสเปซ | owner |
source_path |
{ok, workspace_id} |
workspace.delete |
กลายพันธุ์ | การติดตั้ง* | owner |
id |
แถวในทะเบียนถูกทำเครื่องหมายว่าลบแล้ว |
workspace.deleteไม่มีขอบเขตเพราะแถวที่มันทำเครื่องหมายอยู่ในทะเบียน ส่วนกลาง ตัวจัดการของมันตรวจสอบสมาชิกภาพของผู้เรียกในเวิร์กสเปซที่ระบุชื่อ และกำหนดให้ต้องเป็นowner
path ในทุกคำตอบเป็นพาธบนโฮสต์เซิร์ฟเวอร์
คำตอบของ server.listBackups
หัวข้อที่มีชื่อว่า “คำตอบของ server.listBackups”ใหม่สุดก่อน เรียงตามชื่อไดเรกทอรี (ซึ่งก็คือเวลาประทับ ลำดับจึงยังถูกต้องแม้ กับสแนปช็อตที่อ่านแมนิเฟสต์ไม่ได้)
{ "backups": [ { "path": "/…/backups/2026-07-28T09-12-33-000Z", "name": "2026-07-28T09-12-33-000Z", "created_at": "2026-07-28T09:12:33.000Z", "bytes": 481203712, "complete": true, "workspaces": [ { "workspace_id": "w_9f2c…", "path": "/…/backups/2026-07-28T09-12-33-000Z/w_9f2c…/workspace.db", "bytes": 190840832 } ], "skipped_workspace_ids": [] } ]}created_at จะถูกละไว้เมื่ออ่านแมนิเฟสต์ไม่ได้ ส่วน bytes ระดับบนสุดคือ
ขนาดจริงบนดิสก์ของทั้งไดเรกทอรี ไม่ใช่ผลรวมในแมนิเฟสต์เอง — คำถามที่ผู้ดำเนินการ
ซึ่งคัดสแนปช็อตทิ้งถามคือไดเรกทอรีนี้กินพื้นที่เท่าไร ไม่ใช่ว่าข้อมูลสำรอง
ตั้งใจจะเขียนอะไร
workspaces[].path แต่ละรายการคือสิ่งที่ workspace.import รับเป็น source_path
พอดี เป็นเจตนา: “กู้คืนเวิร์กสเปซนี้จากสแนปช็อตนี้” ก็คือ ปฏิบัติการนำเข้า
ทั้งสองจึงแยกไปปฏิบัติต่อไฟล์เดียวกันต่างกันไม่ได้
การตรวจสอบความถูกต้องของ workspace.import
หัวข้อที่มีชื่อว่า “การตรวจสอบความถูกต้องของ workspace.import”ก่อนที่จะแทนที่สิ่งใด ไฟล์ตัวเลือกจะถูกเปิดแบบอ่านเท่านั้นด้วยการเชื่อมต่อ SQLite
ดิบอายุสั้น และอ่านแถว workspace_meta ของมัน
| เงื่อนไข | ผลลัพธ์ |
|---|---|
ไม่ใช่ฐานข้อมูล SQLite ที่อ่านได้ หรือไม่มี workspace_meta |
ปฏิเสธ ไม่มีอะไรถูกแตะต้อง |
| ไอดีเวิร์กสเปซที่บันทึกไว้ ≠ เป้าหมาย | อนุญาต พร้อมบันทึกล็อก นี่คือวิธีทำสำเนาเวิร์กสเปซหรือกู้คืนภายใต้ไอดีใหม่ |
| ไอดีการติดตั้งที่บันทึกไว้ ≠ การติดตั้งนี้ | อนุญาต พร้อมบันทึกล็อก อุปกรณ์ที่จับคู่และไอดีผู้ใช้ของมันเป็นของการติดตั้งนั้นและจะรีโซลฟ์ที่นี่ไม่ได้ |
| ไอดีเวิร์กสเปซไม่ถูกต้อง หรือไฟล์ไม่มีอยู่ | ปฏิเสธ |
เมื่อรับ ฐานข้อมูลของเวิร์กสเปซเป้าหมายจะถูกปิดและถอดออกจากตัวจัดการ
ก่อนคัดลอกไฟล์ทับ (การเชื่อมต่อ drift ที่เปิดอยู่จะยึดไฟล์และ -wal ของมันไว้)
จากนั้นเปิดใหม่เพื่อให้ beforeOpen ติดตั้งทริกเกอร์ FTS และซิงก์ใหม่ และดัชนี
FTS ถูกสร้างใหม่ — ตารางเนื้อหาของไฟล์ที่นำเข้ามีข้อมูลครบ แต่ดัชนีของมันอาจ
ล้าสมัย
เส้นทางถ่ายโอน
หัวข้อที่มีชื่อว่า “เส้นทางถ่ายโอน”ทุกปฏิบัติการข้างต้นพูดถึงพาธฝั่งเซิร์ฟเวอร์ ซึ่งเป็นคำตอบที่ครบถ้วนเฉพาะเมื่อ
เซิร์ฟเวอร์คือเครื่องของคุณเอง สามเส้นทางนี้ขนย้ายไบต์ บนเลนที่ลงนามด้วย PSK
เส้นเดียวกับที่พร็อกซีสื่อและที่เก็บบล็อบใช้อยู่ ผู้เรียกเซ็นสตริงเป้าหมายด้วย
คีย์ที่แชร์ล่วงหน้าของอุปกรณ์ แล้วส่งลายเซ็นมาเป็น s
| เส้นทาง | เมธอด | คำค้น | เป้าหมายที่ลงนาม | ต้องมี |
|---|---|---|---|---|
/backup/workspace |
GET | w, d, s |
backup-workspace:<workspaceId> |
แอดมิน เวิร์กสเปซ |
/backup/snapshot |
GET | n, d, s |
backup-snapshot:<name> |
เจ้าของ การติดตั้ง |
/backup/restore |
POST | w, d, s |
backup-restore:<workspaceId> |
เจ้าของ เวิร์กสเปซ |
w คือไอดีเวิร์กสเปซ n คือชื่อไดเรกทอรีสแนปช็อต d คือไอดีอุปกรณ์ที่เรียก
s คือลายเซ็น n ถูกตรีสินกับรายการข้อมูลสำรอง ไม่ใช่ต่อเข้ากับรากของ backups
เส้นทางจึงไม่อาจเล็งไปที่ไดเรกทอรีที่รายการไม่เคยแสดง
| สถานะ | สาเหตุ |
|---|---|
400 |
พารามิเตอร์คำค้นที่จำเป็นหายไป หรือบอดี้อัปโหลดว่างเปล่า |
403 |
อุปกรณ์ไม่รู้จักหรือถูกเพิกถอน ลายเซ็นไม่ถูกต้อง หรือผู้เรียกไม่มีบทบาทนั้น |
404 |
ไม่มีพอร์ตสำรองบนโฮสต์นี้ หรือสแนปช็อต/ไฟล์เวิร์กสเปซที่ระบุชื่อไม่มีอยู่ |
405 |
เรียก /backup/restore ด้วยเมธอดอื่นที่ไม่ใช่ POST |
413 |
บอดี้อัปโหลดเกิน 8 GiB ไม่ว่าจะตาม content-length ที่ประกาศไว้หรือตามไบต์ที่อ่านจริง |
500 |
การส่งออกหรือสร้างอาร์ไคฟ์ล้มเหลวฝั่งเซิร์ฟเวอร์ |
การดาวน์โหลดทั้งสองตอบกลับด้วย Cache-Control: no-store พร้อม Accept-Ranges: none
แต่ละคำขอสร้างสำเนาใหม่และลบทิ้งเมื่อสตรีมจบ คำตอบที่ถูกแคชหรือสตรีมต่อ
จึงจะเชื่อมไบต์จากการส่งออกสองครั้งที่ต่างกันเข้าเป็นไฟล์เดียวที่ดูเหมือนถูกต้องแต่ไม่ใช่
/backup/snapshot ส่งคืน <name>.zip โดยรายการภายในอ้างจากรากของสแนปช็อต
การแตกไฟล์จึงสร้าง manifest.json + global.db + <workspaceId>/workspace.db
กลับขึ้นมาซ้ำ รายการถูกเขียนตามลำดับที่เรียงแล้ว อาร์ไคฟ์สองชุดของสแนปช็อตเดียวกัน
จึงเป็นอาร์ไคฟ์เดียวกัน
/backup/restore สตรีมบอดี้ออกไปยังไฟล์พักโดยตรงแทนการบัฟเฟอร์ จำกัดขนาดมัน
ก่อนและระหว่างการอ่าน และลบไฟล์ที่พักไว้ในทุกเส้นทางที่ออกไป
รวมถึงกรณีถูกปฏิเสธ
พาธและขีดจำกัด
หัวข้อที่มีชื่อว่า “พาธและขีดจำกัด”| สิ่ง | ค่า |
|---|---|
| สแนปช็อต | <dataDir>/backups/<timestamp>/ |
| ข้อมูลสำรองของเวิร์กสเปซตามกำหนดเวลา | <dataDir>/backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db |
| การส่งออกเวิร์กสเปซ | <dataDir>/backups/exports/<workspaceId>-<timestamp>.db |
| การพักการถ่ายโอน | <dataDir>/backups/transfer/ — โต๊ะทำงานที่ถูกกวาดเก็บโดยเส้นทางที่เขียนมัน |
| ชื่ออาร์ไคฟ์สแนปช็อต | <snapshot directory name>.zip |
| เพดานการอัปโหลด | 8 GiB ต่อ POST /backup/restore |
| การเก็บรักษา | สแนปช็อตการติดตั้ง: ลบด้วยมือ ข้อมูลสำรองของเวิร์กสเปซ: ไปป์ไลน์รายสัปดาห์ ค่าเริ่มต้น 30 วัน |
ไดเรกทอรี exports/, transfer/ และ workspace-backups/ ไม่ใช่
สแนปช็อตการติดตั้งและถูกตัดออกจาก server.listBackups มีเพียงไดเรกทอรี
สุดท้ายเท่านั้นที่มีการเก็บรักษาตามกำหนด การลบสแนปช็อตการติดตั้งต้องมี
การดำเนินการอย่างชัดแจ้งของเจ้าของการติดตั้ง
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- สำรองและกู้คืน — สูตรงานที่ปฏิบัติการเหล่านี้เป็นส่วนหนึ่ง
- เวิร์กสเปซและการแยกโดเมน — เหตุใดหนึ่งเวิร์กสเปซคือหนึ่งไฟล์
cc_serverCLI — ไดเรกทอรีข้อมูลที่พาธเหล่านี้อยู่- แผนที่เส้นทาง — ที่อยู่ของส่วนติดต่อผู้ใช้
- สถาปัตยกรรม — การแยกไคลเอนต์/เซิร์ฟเวอร์ที่พาธเหล่านี้ยึดตาม