Skip to content

sharding分库,default库不在分库中时异常 #4270

@fulltimelink

Description

@fulltimelink

Go version

go1.23.2. darwin/arm64

GoFrame version

2.8.3

Can this bug be reproduced with the latest release?

Option Yes

What did you do?

按照分库分表示例进行,其中数据库配置如下:

database:
  default:
    link: "mysql:root:root@tcp(127.0.0.1:3306)/gf"
  db_0:
    link: "mysql:root:root@tcp(127.0.0.1:3306)/db_0"
    debug: true
  db_1:
    link: "mysql:root:root@tcp(127.0.0.1:3306)/db_1"
    debug: true
  • default中的gf库不在分库列表中,无“分表”相关表存在

dao sharding:

// userShardingHandler is the handler for sharding operations.
// You can fill this sharding handler with your custom implementation.
func userShardingHandler(m *gdb.Model) *gdb.Model {
	m = m.Sharding(gdb.ShardingConfig{
		Table: gdb.ShardingTableConfig{
			Enable: true,
			Prefix: "order_",
			// Replace Rule field with your custom sharding rule.
			// Or you can use "&gdb.DefaultShardingRule{}" for default sharding rule.
			Rule: &OrderShardingRule{SchemaCount: 2},
		},
		Schema: gdb.ShardingSchemaConfig{
			Enable: true,
			Prefix: "db_",
			Rule:   &OrderShardingRule{SchemaCount: 2},
		},
	})
	return m
}

// Add your custom methods and functionality below.
// ShardingValue 分片值
type OrderShardingValue struct {
	UserId     int64
	CreateTime time.Time
}

// OrderShardingRule 订单分片规则
type OrderShardingRule struct {
	SchemaCount int64 // 分库数量
}

// SchemaName 实现ShardingRule接口中的SchemaName方法
func (r *OrderShardingRule) SchemaName(
	ctx context.Context, config gdb.ShardingSchemaConfig, value any,
) (string, error) {
	if r.SchemaCount <= 0 {
		return "", gerror.New("schema count should be greater than 0")
	}
	// 获取用户ID
	sv, ok := value.(OrderShardingValue)
	if !ok {
		return "", gerror.New("invalid sharding value")
	}
	userId := sv.UserId
	if userId <= 0 {
		return "", gerror.New("invalid user_id for sharding")
	}
	// 按用户ID取模确定分库
	schemaIndex := userId % r.SchemaCount
	return fmt.Sprintf("%s%d", config.Prefix, schemaIndex), nil
}

// TableName 实现ShardingRule接口中的TableName方法
func (r *OrderShardingRule) TableName(
	ctx context.Context, config gdb.ShardingTableConfig, value any,
) (string, error) {
	// 获取订单创建时间
	sv, ok := value.(OrderShardingValue)
	if !ok {
		return "", gerror.New("invalid sharding value")
	}
	createTime := sv.CreateTime
	if createTime.IsZero() {
		return "", gerror.New("invalid create_time for sharding")
	}
	// 按月份确定分表
	tableName := fmt.Sprintf(
		"%s%d%02d", config.Prefix, createTime.Year(), createTime.Month(),
	)
	return tableName, nil
}

What did you see happen?

{
    "code": 52,
    "message": "SHOW FULL COLUMNS FROM `order_202505`: Error 1146 (42S02): Table 'gf.order_202505' doesn't exist",
    "data": {
        "orderId": "1xe67u01q7od9masns21re8100p1289k"
    }
}

What did you expect to see?

正常分库分表


debug了下,应该是DriverWrapperDB的DoInsert 方法中 使用gdb.Core 的ConvertDataForRecord 方法时未使用正确的schema触发的异常。

func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) {
	// Convert data type before commit it to underlying db driver.
	for i, item := range list {
		list[i], err =  d.GetCore().ConvertDataForRecord(ctx, item, table)
		if err != nil {
			return nil, err
		}
	}
	return d.DB.DoInsert(ctx, link, table, list, option)
}

给Core方法追加SetSchema方法,并在HookInsertInput的Next方法中设置正确的Schema后测试正常。

func (c *Core) SetSchema(s string){
	c.schema = s
}
......

// Next calls the next hook handler.
func (h *HookInsertInput) Next(ctx context.Context) (result sql.Result, err error) {
	........

	// Schema change.
	if h.Schema != "" && h.Schema != h.originalSchemaName.String() {
		h.link, err = h.Model.db.GetCore().MasterLink(h.Schema)
		if err != nil {
			return
		}
                // --  @# 测试给Core设置Schema
		h.Model.db.GetCore().SetSchema(h.Schema)
	}
	return h.Model.db.DoInsert(ctx, h.link, h.Table, h.Data, h.Option)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIt is confirmed a bug, but don't worry, we'll handle it.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions