

文件版本模型:
{
"file_id": "file_001",
"filename": "document.pdf",
"versions": [
{
"version_id": "v1",
"version_number": 1,
"size": 1024000,
"hash": "abc123",
"created_at": "2024-01-01T10:00:00Z",
"created_by": "user_001",
"description": "初始版本",
"status": "active"
},
{
"version_id": "v2",
"version_number": 2,
"size": 1234567,
"hash": "def456",
"created_at": "2024-01-02T14:30:00Z",
"created_by": "user_002",
"description": "修改内容",
"status": "active",
"parent_version": "v1"
}
],
"current_version": "v2",
"total_versions": 2,
"created_at": "2024-01-01T10:00:00Z",
"updated_at": "2024-01-02T14:30:00Z"
}版本表结构:
字段 | 类型 | 说明 |
|---|---|---|
version_id | VARCHAR(64) | 版本唯一标识 |
file_id | VARCHAR(64) | 文件唯一标识 |
version_number | INT | 版本号 |
size | BIGINT | 文件大小 |
hash | VARCHAR(64) | 文件哈希值 |
content_path | VARCHAR(255) | 内容存储路径 |
created_at | DATETIME | 创建时间 |
created_by | VARCHAR(64) | 创建人 |
description | TEXT | 版本描述 |
status | VARCHAR(20) | 状态 |
parent_version | VARCHAR(64) | 父版本ID |
版本创建流程:

版本创建代码示例:
import hashlib
import os
import uuid
class VersionManager:
def __init__(self, db, storage):
self.db = db
self.storage = storage
def calculate_hash(self, file_content):
return hashlib.md5(file_content).hexdigest()
def get_next_version_number(self, file_id):
result = self.db.execute(
"SELECT MAX(version_number) FROM file_versions WHERE file_id = %s",
(file_id,)
)
max_version = result.fetchone()[0]
return (max_version or 0) + 1
def create_version(self, file_id, filename, file_content, created_by, description=''):
file_hash = self.calculate_hash(file_content)
existing_version = self.db.execute(
"SELECT version_id FROM file_versions WHERE file_id = %s AND hash = %s",
(file_id, file_hash)
).fetchone()
if existing_version:
version_id = existing_version[0]
print(f"Hash already exists, reusing version {version_id}")
else:
version_id = f"v{str(uuid.uuid4())[:8]}"
content_path = self.storage.save(file_hash, file_content)
parent_version = self._get_current_version(file_id)
self.db.execute(
"""
INSERT INTO file_versions
(version_id, file_id, version_number, size, hash, content_path,
created_by, description, parent_version)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
(version_id, file_id, self.get_next_version_number(file_id),
len(file_content), file_hash, content_path,
created_by, description, parent_version)
)
self.db.execute(
"UPDATE files SET current_version = %s, updated_at = NOW() WHERE file_id = %s",
(version_id, file_id)
)
self._log_operation(file_id, version_id, created_by, 'create')
return version_id
def _get_current_version(self, file_id):
result = self.db.execute(
"SELECT current_version FROM files WHERE file_id = %s",
(file_id,)
).fetchone()
if result:
return result[0]
return None
def _log_operation(self, file_id, version_id, user_id, operation):
self.db.execute(
"""
INSERT INTO version_history
(file_id, version_id, user_id, operation, created_at)
VALUES (%s, %s, %s, %s, NOW())
""",
(file_id, version_id, user_id, operation)
)版本对比流程:

版本对比代码示例:
import difflib
class VersionComparator:
def __init__(self, storage):
self.storage = storage
def compare_text(self, version1_content, version2_content):
lines1 = version1_content.decode('utf-8').splitlines()
lines2 = version2_content.decode('utf-8').splitlines()
differ = difflib.Differ()
diff = list(differ.compare(lines1, lines2))
additions = [line[2:] for line in diff if line.startswith('+ ')]
deletions = [line[2:] for line in diff if line.startswith('- ')]
changes = [line[2:] for line in diff if line.startswith('? ')]
return {
'additions': additions,
'deletions': deletions,
'changes': changes,
'total_changes': len(additions) + len(deletions)
}
def compare_binary(self, version1_content, version2_content):
if version1_content == version2_content:
return {'is_same': True, 'differences': 0}
differences = 0
min_length = min(len(version1_content), len(version2_content))
for i in range(min_length):
if version1_content[i] != version2_content[i]:
differences += 1
differences += abs(len(version1_content) - len(version2_content))
return {
'is_same': False,
'differences': differences,
'percentage_different': (differences / max(len(version1_content), len(version2_content))) * 100
}
def compare_versions(self, version1, version2):
content1 = self.storage.get(version1['content_path'])
content2 = self.storage.get(version2['content_path'])
file_extension = os.path.splitext(version1.get('filename', ''))[1].lower()
if file_extension in ['.txt', '.md', '.csv', '.json', '.xml']:
return self.compare_text(content1, content2)
else:
return self.compare_binary(content1, content2)版本回退流程:

版本回退代码示例:
class VersionRollback:
def __init__(self, db, storage):
self.db = db
self.storage = storage
def rollback(self, file_id, target_version_id, user_id):
target_version = self.db.execute(
"SELECT * FROM file_versions WHERE version_id = %s AND file_id = %s",
(target_version_id, file_id)
).fetchone()
if not target_version:
return {'success': False, 'message': 'Version not found'}
new_version_number = self._get_next_version_number(file_id)
new_version_id = f"v{str(uuid.uuid4())[:8]}"
self.db.execute(
"""
INSERT INTO file_versions
(version_id, file_id, version_number, size, hash, content_path,
created_by, description, parent_version)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
(new_version_id, file_id, new_version_number,
target_version[3], target_version[4], target_version[5],
user_id, f"Rollback to version {target_version_id}",
target_version[0])
)
self.db.execute(
"UPDATE files SET current_version = %s, updated_at = NOW() WHERE file_id = %s",
(new_version_id, file_id)
)
self._log_operation(file_id, new_version_id, user_id, 'rollback')
return {
'success': True,
'message': 'Rollback successful',
'new_version_id': new_version_id,
'rolled_back_from': target_version_id
}
def _get_next_version_number(self, file_id):
result = self.db.execute(
"SELECT MAX(version_number) FROM file_versions WHERE file_id = %s",
(file_id,)
)
max_version = result.fetchone()[0]
return (max_version or 0) + 1
def _log_operation(self, file_id, version_id, user_id, operation):
self.db.execute(
"""
INSERT INTO version_history
(file_id, version_id, user_id, operation, created_at)
VALUES (%s, %s, %s, %s, NOW())
""",
(file_id, version_id, user_id, operation)
)
操作日志表结构:
字段 | 类型 | 说明 |
|---|---|---|
log_id | VARCHAR(64) | 日志唯一标识 |
file_id | VARCHAR(64) | 文件唯一标识 |
version_id | VARCHAR(64) | 版本唯一标识 |
user_id | VARCHAR(64) | 用户唯一标识 |
operation | VARCHAR(20) | 操作类型 |
details | TEXT | 操作详情 |
created_at | DATETIME | 操作时间 |
ip_address | VARCHAR(50) | 操作IP |
操作类型:
操作类型 | 说明 |
|---|---|
create | 创建文件 |
update | 更新文件 |
delete | 删除文件 |
version_create | 创建版本 |
version_rollback | 版本回退 |
download | 下载文件 |
share | 分享文件 |
变更记录表结构:
字段 | 类型 | 说明 |
|---|---|---|
change_id | VARCHAR(64) | 变更唯一标识 |
file_id | VARCHAR(64) | 文件唯一标识 |
field_name | VARCHAR(100) | 变更字段 |
old_value | TEXT | 旧值 |
new_value | TEXT | 新值 |
changed_by | VARCHAR(64) | 变更人 |
changed_at | DATETIME | 变更时间 |
变更记录代码示例:
class ChangeRecorder:
def __init__(self, db):
self.db = db
def record_change(self, file_id, field_name, old_value, new_value, changed_by):
if old_value == new_value:
return
self.db.execute(
"""
INSERT INTO file_changes
(change_id, file_id, field_name, old_value, new_value, changed_by, changed_at)
VALUES (%s, %s, %s, %s, %s, %s, NOW())
""",
(str(uuid.uuid4()), file_id, field_name, old_value, new_value, changed_by)
)
def get_changes(self, file_id, limit=100):
result = self.db.execute(
"""
SELECT * FROM file_changes
WHERE file_id = %s
ORDER BY changed_at DESC
LIMIT %s
""",
(file_id, limit)
)
columns = [desc[0] for desc in result.description]
return [dict(zip(columns, row)) for row in result.fetchall()]
def get_field_changes(self, file_id, field_name, limit=50):
result = self.db.execute(
"""
SELECT * FROM file_changes
WHERE file_id = %s AND field_name = %s
ORDER BY changed_at DESC
LIMIT %s
""",
(file_id, field_name, limit)
)
columns = [desc[0] for desc in result.description]
return [dict(zip(columns, row)) for row in result.fetchall()]审计追踪流程:

审计报告示例:
{
"audit_id": "audit_001",
"audit_time": "2024-01-15T10:00:00Z",
"file_id": "file_001",
"filename": "document.pdf",
"history": [
{
"timestamp": "2024-01-01T10:00:00Z",
"user": "user_001",
"operation": "create",
"version": "v1",
"details": "Created initial version"
},
{
"timestamp": "2024-01-02T14:30:00Z",
"user": "user_002",
"operation": "version_create",
"version": "v2",
"details": "Updated content"
},
{
"timestamp": "2024-01-05T09:15:00Z",
"user": "user_001",
"operation": "version_rollback",
"version": "v3",
"details": "Rolled back to v1"
}
],
"total_operations": 3,
"unique_users": 2,
"time_range": {
"start": "2024-01-01T10:00:00Z",
"end": "2024-01-05T09:15:00Z"
}
}版本备份流程:

版本备份代码示例:
import zipfile
import json
class VersionBackup:
def __init__(self, db, storage):
self.db = db
self.storage = storage
def backup_file_versions(self, file_id, backup_path):
versions = self.db.execute(
"SELECT * FROM file_versions WHERE file_id = %s ORDER BY version_number",
(file_id,)
).fetchall()
version_data = []
for version in versions:
content = self.storage.get(version[5])
version_info = {
'version_id': version[0],
'version_number': version[2],
'hash': version[4],
'content_path': version[5],
'created_at': version[6],
'created_by': version[7],
'description': version[8]
}
version_data.append(version_info)
with zipfile.ZipFile(backup_path, 'w') as zipf:
zipf.writestr('metadata.json', json.dumps(version_data, indent=2))
for version in versions:
content = self.storage.get(version[5])
zipf.writestr(f"versions/{version[0]}", content)
return {'success': True, 'backup_path': backup_path, 'versions_count': len(versions)}
def restore_file_versions(self, file_id, backup_path):
with zipfile.ZipFile(backup_path, 'r') as zipf:
metadata = json.loads(zipf.read('metadata.json').decode())
for version_info in metadata:
content = zipf.read(f"versions/{version_info['version_id']}")
existing = self.db.execute(
"SELECT version_id FROM file_versions WHERE file_id = %s AND hash = %s",
(file_id, version_info['hash'])
).fetchone()
if not existing:
self.db.execute(
"""
INSERT INTO file_versions
(version_id, file_id, version_number, size, hash, content_path,
created_by, description)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""",
(version_info['version_id'], file_id, version_info['version_number'],
len(content), version_info['hash'],
self.storage.save(version_info['hash'], content),
version_info['created_by'], version_info['description'])
)
latest_version = metadata[-1]['version_id']
self.db.execute(
"UPDATE files SET current_version = %s WHERE file_id = %s",
(latest_version, file_id)
)
return {'success': True, 'versions_restored': len(metadata)}版本同步流程:

增量存储原理:

增量存储代码示例:
class DeltaStorage:
def __init__(self, storage):
self.storage = storage
def compute_delta(self, old_content, new_content):
deltas = []
old_pos = 0
new_pos = 0
while old_pos < len(old_content) or new_pos < len(new_content):
if old_pos < len(old_content) and new_pos < len(new_content):
if old_content[old_pos] == new_content[new_pos]:
if deltas and deltas[-1]['type'] == 'equal':
deltas[-1]['length'] += 1
else:
deltas.append({'type': 'equal', 'length': 1})
old_pos += 1
new_pos += 1
else:
insert_start = new_pos
while new_pos < len(new_content) and (old_pos >= len(old_content) or old_content[old_pos] != new_content[new_pos]):
new_pos += 1
deltas.append({'type': 'insert', 'data': new_content[insert_start:new_pos]})
elif new_pos < len(new_content):
deltas.append({'type': 'insert', 'data': new_content[new_pos:]})
break
else:
break
return deltas
def save_delta(self, base_version_id, deltas):
delta_id = str(uuid.uuid4())
delta_path = self.storage.save(delta_id, json.dumps(deltas).encode())
return {'delta_id': delta_id, 'delta_path': delta_path}
def apply_delta(self, base_content, deltas):
result = bytearray()
old_pos = 0
for delta in deltas:
if delta['type'] == 'equal':
result.extend(base_content[old_pos:old_pos + delta['length']])
old_pos += delta['length']
elif delta['type'] == 'insert':
result.extend(delta['data'])
return bytes(result)版本清理策略:
策略 | 说明 | 适用场景 |
|---|---|---|
保留最新N个 | 保留最近N个版本 | 存储空间有限 |
按时间保留 | 保留指定时间内的版本 | 合规要求 |
按大小清理 | 按总大小清理 | 存储成本控制 |
用户选择 | 用户手动选择保留 | 灵活控制 |
版本清理代码示例:
class VersionCleanup:
def __init__(self, db, storage):
self.db = db
self.storage = storage
def cleanup_by_count(self, file_id, keep_count=5):
versions = self.db.execute(
"""
SELECT version_id, hash FROM file_versions
WHERE file_id = %s
ORDER BY version_number DESC
""",
(file_id,)
).fetchall()
if len(versions) <= keep_count:
return {'success': True, 'deleted_count': 0}
versions_to_delete = versions[keep_count:]
for version in versions_to_delete:
self.db.execute(
"DELETE FROM file_versions WHERE version_id = %s",
(version[0],)
)
hash_count = self.db.execute(
"SELECT COUNT(*) FROM file_versions WHERE hash = %s",
(version[1],)
).fetchone()[0]
if hash_count == 0:
self.storage.delete(version[1])
return {'success': True, 'deleted_count': len(versions_to_delete)}
def cleanup_by_date(self, file_id, days_to_keep=30):
versions = self.db.execute(
"""
SELECT version_id, hash FROM file_versions
WHERE file_id = %s AND created_at < DATE_SUB(NOW(), INTERVAL %s DAY)
""",
(file_id, days_to_keep)
).fetchall()
for version in versions:
self.db.execute(
"DELETE FROM file_versions WHERE version_id = %s",
(version[0],)
)
hash_count = self.db.execute(
"SELECT COUNT(*) FROM file_versions WHERE hash = %s",
(version[1],)
).fetchone()[0]
if hash_count == 0:
self.storage.delete(version[1])
return {'success': True, 'deleted_count': len(versions)}现象:版本数据丢失
解决方案:
方案 | 说明 |
|---|---|
定期备份 | 定期备份版本数据 |
多副本存储 | 使用多副本存储 |
完整性校验 | 定期校验版本完整性 |
现象:版本存储占用大量空间
解决方案:
方案 | 说明 |
|---|---|
增量存储 | 使用增量存储 |
版本清理 | 清理旧版本 |
压缩存储 | 压缩版本内容 |
现象:无法追溯版本变更历史
解决方案:
方案 | 说明 |
|---|---|
完善日志 | 完善操作日志 |
变更记录 | 记录详细变更 |
审计报告 | 生成审计报告 |
现象:多人同时修改导致版本冲突
解决方案:
方案 | 说明 |
|---|---|
锁机制 | 使用锁机制 |
冲突检测 | 检测版本冲突 |
合并策略 | 制定合并策略 |
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。