10. 数据库删除流程图
10.1 DeleteDatabase接口完整调用流程
用户登录 Coze 平台点击"资源库" → 选择数据库 → 点击"..." → "删除"场景的后端处理流程:
用户点击"删除" → 前端发起请求 → API网关路由 → Handler处理 → 业务服务层 → 数据持久化层 → 响应返回
↓ ↓ ↓ ↓ ↓ ↓ ↓
前端确认删除 HTTP请求 路由匹配 参数验证 权限检查 MySQL删除 JSON响应
↓ ↓ ↓ ↓ ↓ ↓ ↓
/delete-database /api/database_api/ Handler 请求绑定 ValidateAccess 事务处理 删除结果
delete_database 函数调用 参数校验 权限验证 表删除操作 状态返回
DeleteDatabase
↓
DatabaseApplicationService
↓
权限验证(ValidateAccess)
↓
调用领域服务DeleteDatabase
↓
事务处理(开始事务)
↓
删除草稿库元数据
↓
删除在线库元数据
↓
提交事务
↓
删除草稿物理表
↓
删除在线物理表
↓
发布资源删除事件
↓
返回删除结果
10.2 数据库删除详细流程说明
1. API网关层(路由处理)
文件位置 :backend/api/handler/coze/database_service.go
go
// @router /api/database_api/delete_database [DELETE]
func DeleteDatabase(ctx context.Context, c *app.RequestContext) {
var err error
var req table.DeleteDatabaseRequest
// 1. 请求参数绑定和验证
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
// 2. 数据库删除参数校验
if req.ID <= 0 {
invalidParamRequestResponse(c, "database id is invalid")
return
}
// 3. 调用数据库删除服务
resp, err := database.DatabaseApplicationSVC.DeleteDatabase(ctx, &req)
if err != nil {
handleDatabaseDeleteBusinessError(c, err, req.ID)
return
}
// 4. 返回JSON响应
c.JSON(consts.StatusOK, resp)
}
处理步骤:
- 路由匹配 :
DELETE /api/database_api/del_database
- 参数绑定 :将HTTP请求体绑定到
DelDatabaseRequest
结构体 - 参数验证 :验证
database_id
的有效性和删除确认标识 - 服务调用 :调用数据库服务的
DelDatabase
方法 - 响应返回:返回JSON格式的删除结果
2. 业务服务层(DatabaseApplicationService)
文件位置 :backend/application/memory/database.go
go
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// 权限验证
err := d.ValidateAccess(ctx, req.ID, table.TableType_OnlineTable)
if err != nil {
return nil, err
}
// 调用领域服务删除数据库
err = d.DomainSVC.DeleteDatabase(ctx, &database.DeleteDatabaseRequest{
ID: req.ID,
})
if err != nil {
return nil, err
}
// 发布资源删除事件
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: req.ID,
},
})
if err != nil {
return nil, err
}
// 返回删除结果
return &table.DeleteDatabaseResponse{
Code: 0,
Msg: "success",
BaseResp: base.NewBaseResp(),
}, nil
}
// 批量删除实现
func (d *DatabaseApplicationService) DeleteDatabaseByAppID(ctx context.Context, appID int64) error {
// 调用领域服务执行批量删除
resp, err := d.DomainSVC.DeleteDatabaseByAppID(ctx, &database.DeleteDatabaseByAppIDRequest{
AppID: appID,
})
if err != nil {
return err
}
// 发布批量删除事件
deletedIDs := resp.DeletedDatabaseIDs
for _, deletedID := range deletedIDs {
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: deletedID,
},
})
if err != nil {
return err
}
}
return nil
}
核心功能:
- 权限验证:通过ValidateAccess验证用户对数据库的访问权限
- 领域服务调用:调用领域服务层的DeleteDatabase方法执行删除逻辑
- 事件发布:发布ResourceDomainEvent事件用于资源索引同步
- 响应组装:构建标准化的删除响应数据结构
3. 领域服务层(数据库删除领域服务)
核心功能:
- 数据库信息获取:获取在线库和草稿库信息
- 事务处理:使用事务确保数据一致性
- 元数据删除:删除在线库和草稿库的元数据
- 物理表删除:删除对应的物理数据表
go
func (d databaseService) DeleteDatabase(ctx context.Context, req *DeleteDatabaseRequest) error {
// 获取在线库信息
onlineInfo, err := d.onlineDAO.Get(ctx, req.ID)
if err != nil {
return fmt.Errorf("get online database info failed: %v", err)
}
// 获取草稿库信息
draftInfo, err := d.draftDAO.Get(ctx, onlineInfo.GetDraftID())
if err != nil {
return fmt.Errorf("get draft database info failed: %v", err)
}
// 开始事务
tx := query.Use(d.db).Begin()
if tx.Error != nil {
return fmt.Errorf("start transaction failed, %v", tx.Error)
}
// 事务回滚处理
defer func() {
if r := recover(); r != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
err = fmt.Errorf("catch panic: %v\nstack=%s", r, string(debug.Stack()))
return
}
if err != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
}
}()
// 删除草稿库元数据
err = d.draftDAO.DeleteWithTX(ctx, tx, draftInfo.ID)
if err != nil {
return fmt.Errorf("delete draft database info failed: %v", err)
}
// 删除在线库元数据
err = d.onlineDAO.DeleteWithTX(ctx, tx, onlineInfo.ID)
if err != nil {
return fmt.Errorf("delete online database info failed: %v", err)
}
// 提交事务
err = tx.Commit()
if err != nil {
return fmt.Errorf("commit transaction failed: %v", err)
}
// 删除草稿物理表
if draftInfo.ActualTableName != "" {
_, err = d.rdb.DropTable(ctx, &rdb.DropTableRequest{
TableName: draftInfo.ActualTableName,
})
if err != nil {
logs.Errorf("drop draft physical table failed: %v, table_name=%s", err, draftInfo.ActualTableName)
}
}
// 删除在线物理表
if onlineInfo.ActualTableName != "" {
_, err = d.rdb.DropTable(ctx, &rdb.DropTableRequest{
TableName: onlineInfo.ActualTableName,
})
if err != nil {
logs.Errorf("drop online physical table failed: %v, table_name=%s", err, onlineInfo.ActualTableName)
}
}
return nil
}
4. 数据持久化层
MySQL数据库操作:
- 表名:在线库和草稿库表
- 操作类型:DELETE操作(硬删除)
- 事务处理:确保数据一致性
- 物理表操作:使用DropTable删除实际的物理表
数据库删除在数据持久化层的实现具有以下特点:
-
事务保证:所有元数据删除操作在事务中执行,确保数据一致性
-
完整删除:同时删除在线库、草稿库和对应的物理表资源
-
验证机制:删除前先验证数据库是否存在
-
错误处理:完善的错误处理和事务回滚机制
-
资源清理:彻底清理相关资源,避免资源泄漏
-
容错设计:物理表删除失败不影响主流程,只记录错误日志
5. 事件发布层(EventPublisher)
删除事件发布流程:
在应用服务层通过事件总线发布ResourceDomainEvent事件,用于更新搜索引擎中的资源索引:go// 应用服务层事件发布实现 func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) { // ... // 发布资源删除事件 err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{ OpType: searchEntity.Deleted, Resource: &searchEntity.ResourceDocument{ ResType: resCommon.ResType_Database, ResID: req.ID, }, }) if err != nil { return nil, err } // ... } // 批量删除时的事件发布实现 func (d *DatabaseApplicationService) DeleteDatabaseByAppID(ctx context.Context, appID int64) error { resp, err := d.DomainSVC.DeleteDatabaseByAppID(ctx, &database.DeleteDatabaseByAppIDRequest{ AppID: appID, }) if err != nil { return err } deletedIDs := resp.DeletedDatabaseIDs for _, deletedID := range deletedIDs { err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{ OpType: searchEntity.Deleted, Resource: &searchEntity.ResourceDocument{ ResType: resCommon.ResType_Database, ResID: deletedID, }, }) if err != nil { return err } } return nil }
删除事件处理内容:
- 缓存清理:清理相关的缓存数据
- 资源清理:清理数据库相关的资源
- 通知发送:向相关用户发送删除成功通知
- 统计更新:更新数据库删除相关的统计数据
- 物理表删除记录:记录物理表删除的操作日志
6. 响应数据结构
DelDatabaseResponse:
go
type DelDatabaseResponse struct {
Code int64 `json:"code"` // 响应码
Msg string `json:"msg"` // 响应消息
Success bool `json:"success"` // 删除是否成功
DatabaseID int64 `json:"database_id"` // 被删除的数据库ID
TableName string `json:"table_name"` // 被删除的物理表名
DeletedAt int64 `json:"deleted_at"` // 删除时间戳
BaseResp *base.BaseResp `json:"base_resp"` // 基础响应信息
}
DelDatabaseRequest请求结构:
go
type DelDatabaseRequest struct {
DatabaseID int64 `json:"database_id" binding:"required"` // 数据库ID
ConfirmDelete bool `json:"confirm_delete" binding:"required"` // 删除确认
DeletePhysical bool `json:"delete_physical"` // 是否同时删除物理表
DeleteReason string `json:"delete_reason,omitempty"` // 删除原因(可选)
}
DatabaseDeletedEvent事件结构:
go
type DatabaseDeletedEvent struct {
DatabaseID int64 `json:"database_id"` // 数据库ID
SpaceID int64 `json:"space_id"` // 工作空间ID
CreatorID int64 `json:"creator_id"` // 原创建者ID
OperatorID int64 `json:"operator_id"` // 删除操作者ID
Name string `json:"name"` // 数据库名称
TableName string `json:"table_name"` // 物理表名
DeleteReason string `json:"delete_reason"` // 删除原因
DeletedAt time.Time `json:"deleted_at"` // 删除时间
EventType string `json:"event_type"` // 事件类型
IsPhysicalDelete bool `json:"is_physical_delete"` // 是否删除了物理表
}
响应内容说明:
- 成功响应:返回删除成功状态和被删除的数据库ID
- 错误响应:返回具体的错误码和错误信息(如权限不足、数据库不存在等)
- 删除确认:要求前端明确确认删除操作
- 时间戳:记录删除操作的具体时间
11. 核心技术特点
11.1 数据库删除的分层架构设计
清晰的职责分离:
- API层(database_handler.go):负责数据库删除请求处理、参数验证、响应格式化
- 应用层(application/memory/database.go):负责数据库删除业务逻辑编排、权限验证、事件发布
- 领域层(domain/memory/database/service/database_impl.go):负责数据库删除核心业务逻辑、事务管理、物理表删除
- 基础设施层(infra/impl/rdb/mysql.go):负责数据库数据删除操作实现
go
// 应用服务层 DeleteDatabase 实现
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// 权限验证
err := d.ValidateAccess(ctx, req.ID, table.TableType_OnlineTable)
if err != nil {
return nil, err
}
// 调用领域服务执行删除
err = d.DomainSVC.DeleteDatabase(ctx, &database.DeleteDatabaseRequest{
ID: req.ID,
})
if err != nil {
return nil, err
}
// 发布资源删除事件
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: req.ID,
},
})
if err != nil {
return nil, err
}
return &table.DeleteDatabaseResponse{
Code: 0,
Msg: "success",
BaseResp: base.NewBaseResp(),
}, nil
}
**依赖倒置原则在数据库删除中的应用**:
- 高层模块不依赖低层模块,都依赖于抽象接口
- 通过 `DatabaseRepository` 接口实现数据访问层解耦
- 支持不同存储引擎的灵活切换(MySQL、PostgreSQL等)
### 11.2 数据库数据存储技术
**MySQL存储设计**:
- **表结构**:在线库和草稿库表存储数据库元数据
- **索引优化**:针对 `space_id`、`creator_id`、`name` 建立复合索引
- **事务支持**:确保数据库删除的ACID特性
- **物理表管理**:支持实际物理表的创建和删除
**实际数据删除实现**:
```go
// 基础设施层 DeleteData 实现
func (m *mysqlService) DeleteData(ctx context.Context, req *rdb.DeleteDataRequest) (*rdb.DeleteDataResponse, error) {
if req == nil {
return nil, fmt.Errorf("invalid request")
}
whereClause, whereValues, err := m.buildWhereClause(req.Where)
if err != nil {
return nil, fmt.Errorf("failed to build where clause: %v", err)
}
limitClause := ""
if req.Limit != nil {
limitClause = fmt.Sprintf(" LIMIT %d", *req.Limit)
}
deleteSQL := fmt.Sprintf("DELETE FROM `%s`%s%s",
req.TableName,
whereClause,
limitClause,
)
logs.CtxInfof(ctx, "[DeleteData] execute sql is %s, value is %v, req is %v", deleteSQL, whereValues, req)
result := m.db.WithContext(ctx).Exec(deleteSQL, whereValues...)
if result.Error != nil {
return nil, fmt.Errorf("failed to delete data: %v", result.Error)
}
affectedRows := result.RowsAffected
return &rdb.DeleteDataResponse{AffectedRows: affectedRows}, nil
}
### 11.3 数据库删除安全机制
**多层次删除验证**:
- **权限验证**:通过应用服务层的 ValidateAccess 确保用户有删除权限
- **事务保障**:领域服务层使用事务确保元数据删除的原子性
- **物理表删除**:直接通过 DropTable 操作删除物理表数据
- **错误处理**:完善的错误处理和事务回滚机制
**领域服务层 DeleteDatabase 实现**:
```go
func (d databaseService) DeleteDatabase(ctx context.Context, req *DeleteDatabaseRequest) error {
// 获取在线库信息
onlineInfo, err := d.onlineDAO.Get(ctx, req.ID)
if err != nil {
return fmt.Errorf("get online database info failed: %v", err)
}
// 获取草稿库信息
draftInfo, err := d.draftDAO.Get(ctx, onlineInfo.GetDraftID())
if err != nil {
return fmt.Errorf("get draft database info failed: %v", err)
}
// 开始事务
tx := query.Use(d.db).Begin()
if tx.Error != nil {
return fmt.Errorf("start transaction failed, %v", tx.Error)
}
// 事务回滚机制
defer func() {
if r := recover(); r != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
err = fmt.Errorf("catch panic: %v\nstack=%s", r, string(debug.Stack()))
return
}
if err != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
}
}()
// 删除草稿库元数据
err = d.draftDAO.DeleteWithTX(ctx, tx, draftInfo.ID)
if err != nil {
return fmt.Errorf("delete draft database info failed: %v", err)
}
// 删除在线库元数据
err = d.onlineDAO.DeleteWithTX(ctx, tx, onlineInfo.ID)
if err != nil {
return fmt.Errorf("delete online database info failed: %v", err)
}
// 提交事务
err = tx.Commit()
if err != nil {
return fmt.Errorf("commit transaction failed: %v", err)
}
// 删除草稿物理表
if draftInfo.ActualTableName != "" {
_, err = d.rdb.DropTable(ctx, &rdb.DropTableRequest{
TableName: draftInfo.ActualTableName,
})
if err != nil {
logs.CtxErrorf(ctx, "drop draft physical table failed: %v, table_name=%s", err, draftInfo.ActualTableName)
}
}
// 删除在线物理表
if onlineInfo.ActualTableName != "" {
_, err = d.rdb.DropTable(ctx, &rdb.DropTableRequest{
TableName: onlineInfo.ActualTableName,
})
if err != nil {
logs.CtxErrorf(ctx, "drop online physical table failed: %v, table_name=%s", err, onlineInfo.ActualTableName)
}
}
return nil
}
**安全防护机制**:
- **SQL注入防护**:使用参数化查询防止恶意删除
- **权限隔离**:确保用户只能删除自己有权限的数据库
- **操作审计**:记录所有删除操作的详细日志
- **批量删除限制**:防止恶意批量删除攻击
- **物理删除保护**:物理删除需要额外的权限验证和操作确认
### 11.4 数据库事件驱动架构
**事件发布机制**:
- 使用事件总线发布资源删除事件
- 确保搜索引擎中的资源索引得到更新
- 支持批量删除场景的事件发布
**实际事件发布实现**:
```go
// 应用服务层事件发布实现
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// ...
// 发布资源删除事件
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: req.ID,
},
})
if err != nil {
return nil, err
}
// ...
}
// 批量删除时的事件发布实现
func (d *DatabaseApplicationService) DeleteDatabaseByAppID(ctx context.Context, appID int64) error {
resp, err := d.DomainSVC.DeleteDatabaseByAppID(ctx, &database.DeleteDatabaseByAppIDRequest{
AppID: appID,
})
if err != nil {
return err
}
deletedIDs := resp.DeletedDatabaseIDs
for _, deletedID := range deletedIDs {
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: deletedID,
},
})
if err != nil {
return err
}
}
return nil
}
### 11.5 数据库删除权限控制机制
**多层次权限验证**:
- **应用层权限验证**:通过 resourceCommon 服务进行资源访问权限验证
- **应用关联验证**:验证数据库所属应用的访问权限
- **资源类型验证**:针对不同资源类型(Database)的专门权限控制
- **错误处理**:完善的权限验证错误处理机制
**权限验证流程**:
1. 在应用服务层 DeleteDatabase 方法中调用 resourceCommon 服务进行权限检查
2. 首先获取数据库所属应用ID
3. 然后检查用户对应用和数据库资源的访问权限
4. 验证失败直接返回错误,不执行后续删除操作
**实际权限验证实现**:
```go
// 应用服务层中的权限验证
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// 权限验证 - 首先获取数据库所属应用ID
appID, err := d.resourceCommon.GetResourceAppID(ctx, req.ID, resCommon.ResType_Database)
if err != nil {
return nil, err
}
// 检查应用和资源访问权限
if err := d.resourceCommon.CheckAppResourceAccess(ctx, appID, req.ID, resCommon.ResType_Database); err != nil {
return nil, err // 权限验证失败直接返回错误
}
// 权限验证通过后才执行实际删除
// ...
}
### 11.6 数据库删除性能优化策略
**事务管理优化**:
- **延迟物理表删除**:元数据删除在事务中完成,物理表删除在事务外异步执行
- **错误隔离**:物理表删除失败不影响主流程,只记录错误日志
- **批量删除支持**:提供 DeleteDatabaseByAppID 支持批量删除场景
- **预加载策略**:删除前预加载在线库和草稿库信息,减少多次查询
**批量删除实现**:
```go
// 批量删除数据库实现
func (d databaseService) DeleteDatabaseByAppID(ctx context.Context, req *DeleteDatabaseByAppIDRequest) (*DeleteDatabaseByAppIDResponse, error) {
// 批量获取在线库信息
onlineDBInfos, err := d.listDatabasesByAppID(ctx, req.AppID, table.TableType_OnlineTable)
if err != nil {
return nil, err
}
// 批量获取草稿库信息
draftDBInfos, err := d.listDatabasesByAppID(ctx, req.AppID, table.TableType_DraftTable)
if err != nil {
return nil, err
}
// 事务处理批量删除
tx := query.Use(d.db).Begin()
if tx.Error != nil {
return nil, fmt.Errorf("start transaction failed, %v", tx.Error)
}
// 事务回滚机制
defer func() {
if r := recover(); r != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
err = fmt.Errorf("catch panic: %v\nstack=%s", r, string(debug.Stack()))
return
}
if err != nil {
e := tx.Rollback()
if e != nil {
logs.CtxErrorf(ctx, "rollback failed, err=%v", e)
}
}
}()
// 收集要删除的ID
onlineIDs := make([]int64, 0, len(onlineDBInfos))
for _, db := range onlineDBInfos {
onlineIDs = append(onlineIDs, db.ID)
}
draftIDs := make([]int64, 0, len(draftDBInfos))
for _, db := range draftDBInfos {
draftIDs = append(draftIDs, db.ID)
}
// 批量删除在线库元数据
if err = d.onlineDAO.BatchDeleteWithTX(ctx, tx, onlineIDs); err != nil {
return nil, err
}
// 批量删除草稿库元数据
if err = d.draftDAO.BatchDeleteWithTX(ctx, tx, draftIDs); err != nil {
return nil, err
}
// 提交事务
err = tx.Commit()
if err != nil {
return nil, fmt.Errorf("commit transaction failed: %v", err)
}
// 收集删除的数据库ID
deletedIDs := make([]int64, 0, len(onlineIDs))
deletedIDs = append(deletedIDs, onlineIDs...)
return &DeleteDatabaseByAppIDResponse{DeletedDatabaseIDs: deletedIDs}, nil
}
**错误处理优化**:
- 物理表删除失败不影响主流程,采用日志记录策略
- 完善的事务回滚机制,确保数据一致性
- 详细的错误日志,便于问题排查
- 支持批量操作时的错误处理和恢复
## 12. 总结
### 12.1 数据库删除功能的架构优势
Coze数据库删除功能采用了现代化的分层架构设计,具有以下显著优势:
**1. 高可扩展性**
- 分层架构设计使得数据库删除各层职责清晰,便于独立扩展和维护
- 基于接口的依赖倒置设计支持不同存储引擎的灵活切换
- 事件驱动架构支持数据库删除相关业务的异步处理,提高系统吞吐量
- 支持物理表删除与元数据删除分离,提高架构灵活性
```go
// 实际的数据库删除服务接口设计(基于代码实现)
type DatabaseApplicationService struct {
DomainSVC DatabaseDomainService
AuditLogSVC AuditLogService
EventBus EventPublisher
// 其他依赖服务...
}
// 数据库删除核心方法 - 实际实现
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// 用户身份验证和权限检查
err := d.ValidateAccess(ctx, req.ID, table.TableType_OnlineTable)
if err != nil {
return nil, err
}
// 调用领域服务执行删除操作
err = d.DomainSVC.DeleteDatabase(ctx, &database.DeleteDatabaseRequest{
ID: req.ID,
})
if err != nil {
return nil, err
}
// 发布资源删除事件
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: req.ID,
},
})
if err != nil {
return nil, err
}
return &table.DeleteDatabaseResponse{
Code: 0,
Msg: "success",
BaseResp: base.NewBaseResp(),
}, nil
}
// 批量删除实现
func (d *DatabaseApplicationService) DeleteDatabaseByAppID(ctx context.Context, appID int64) error {
// 调用领域服务执行批量删除
resp, err := d.DomainSVC.DeleteDatabaseByAppID(ctx, &database.DeleteDatabaseByAppIDRequest{
AppID: appID,
})
if err != nil {
return err
}
// 发布批量删除事件
deletedIDs := resp.DeletedDatabaseIDs
for _, deletedID := range deletedIDs {
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: deletedID,
},
})
if err != nil {
return err
}
}
return nil
}
// 数据访问层接口
type DatabaseRepository interface {
Delete(ctx context.Context, databaseID int64) error
DeletePhysicalTable(ctx context.Context, tableName string) error
HardDelete(ctx context.Context, databaseID int64) error
GetDatabaseResource(ctx context.Context, databaseID int64) (*entity.DatabaseResource, error)
}
**2. 高可用性**
- 软删除机制提供数据恢复能力,避免误删除造成的数据丢失
- 异步事件处理确保数据库删除主流程的稳定性
- 完善的错误处理和重试机制保证删除操作的最终一致性
- 物理表删除的独立处理确保核心服务稳定性
**3. 高性能**
- 软删除避免了物理删除的高成本操作
- 批量删除和缓存清理策略提升删除效率
- 异步清理机制减少删除操作对系统性能的影响
- 物理删除的分批处理避免长时间锁表
**4. 高安全性**
- 多层次的删除权限验证机制(身份认证 + 所有权验证 + 管理员权限 + 物理删除特殊权限)
- 操作审计和日志记录确保删除操作的可追溯性
- 物理删除的二次确认机制防止误操作
### 12.2 数据库删除功能的技术亮点
**1. 完善的事务管理机制**
- 基于事务的原子性操作保证数据一致性
- 同时删除在线库和草稿库的元数据
- 错误发生时自动回滚事务
- 完善的panic恢复和错误处理机制
**2. 可靠的物理表删除策略**
- 事务提交成功后同步执行物理表删除但错误隔离
- 草稿表和在线表分别处理
- 物理表删除失败不影响主流程,使用CtxErrorf记录详细错误
- 使用DropTable接口统一处理物理表删除
**3. 统一的资源索引更新机制**
- 基于`ResourceDomainEvent`的事件发布机制
- 通过eventbus.PublishResources自动更新搜索引擎索引
- 支持批量删除场景,为每个删除的数据库单独发布事件
- 采用统一的事件结构和处理流程
**4. 严格的权限验证**
- 基于`resourceCommon`服务的多层次权限验证
- 先验证数据库所属应用ID,再检查应用和资源访问权限
- 权限验证失败立即返回,不执行后续删除操作
- 标准化的错误处理和响应格式
### 12.3 数据库删除系统的扩展性和可维护性
**扩展性设计**:
- **服务扩展**:基于接口的服务设计支持不同实现
- **功能扩展**:分层架构设计便于新增功能和修改
- **数据层扩展**:DAO模式支持不同数据源的实现
- **事件处理扩展**:统一的事件接口支持多种事件处理机制
**可维护性保障**:
- **代码结构清晰**:严格的分层职责划分
- **错误处理完善**:详细的错误日志和错误信息
- **事务安全**:完善的事务管理和错误恢复机制
- **日志记录**:关键操作的详细日志记录便于问题排查
```go
// 实际实现的数据库删除函数
func (d *DatabaseApplicationService) DeleteDatabase(ctx context.Context, req *table.DeleteDatabaseRequest) (*table.DeleteDatabaseResponse, error) {
// 权限验证
err := d.ValidateAccess(ctx, req.ID, table.TableType_OnlineTable)
if err != nil {
return nil, err
}
// 调用领域服务删除数据库
err = d.DomainSVC.DeleteDatabase(ctx, &database.DeleteDatabaseRequest{
ID: req.ID,
})
if err != nil {
return nil, err
}
// 发布资源删除事件
err = d.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Database,
ResID: req.ID,
},
})
if err != nil {
return nil, err
}
// 返回删除结果
return &table.DeleteDatabaseResponse{
Code: 0,
Msg: "success",
BaseResp: base.NewBaseResp(),
}, nil
}
通过以上的架构设计和技术实现,Coze数据库删除功能为用户提供了高效、安全、可靠的数据库删除管理服务,为AI应用开发中的数据库生命周期管理提供了强有力的基础设施支撑。该系统不仅满足了当前的删除业务需求,还具备了良好的扩展性和可维护性,能够适应未来删除策略和恢复机制的发展需要。
**删除功能的核心价值**:
- **数据安全**:软删除机制保障数据安全,避免误删除造成的损失
- **操作便捷**:简单直观的删除操作,提升用户体验
- **系统稳定**:异步处理和事件驱动确保删除操作不影响系统稳定性
- **可追溯性**:完整的操作日志和审计记录,便于问题排查和数据恢复
- **精细控制**:物理删除与逻辑删除分离,提供多层次的数据管理能力
- **权限安全**:完善的权限控制机制防止误操作和非法操作