-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Labels
bugIt is confirmed a bug, but don't worry, we'll handle it.It is confirmed a bug, but don't worry, we'll handle it.
Description
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
Labels
bugIt is confirmed a bug, but don't worry, we'll handle it.It is confirmed a bug, but don't worry, we'll handle it.