Skip to content

Commit

Permalink
update: optimize mysql v8.0 ddl instant check (#673)
Browse files Browse the repository at this point in the history
  • Loading branch information
hanchuanchuan authored Aug 25, 2024
1 parent 7c6a1c0 commit 4cffeba
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 14 deletions.
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ type Inc struct {
EnableSetCollation bool `toml:"enable_set_collation" json:"enable_set_collation"`
// 开启sql统计
EnableSqlStatistic bool `toml:"enable_sql_statistic" json:"enable_sql_statistic"`
// 在MySQL8.0检测是否支持 ALGORITHM=INSTANT, 当支持时自动关闭pt-osc/gh-ost.
EnableDDLInstant bool `toml:"enable_ddl_instant" json:"enable_ddl_instant"`

// explain判断受影响行数时使用的规则, 默认值"first"
// 可选值: "first", "max"
Expand Down Expand Up @@ -704,6 +706,7 @@ var defaultConf = Config{
CheckIdentifierUpper: false,
CheckIdentifierLower: false,
CheckReadOnly: true,
EnableDDLInstant: true,
SqlSafeUpdates: -1,
LockWaitTimeout: -1,
SupportCharset: "utf8,utf8mb4",
Expand Down
2 changes: 2 additions & 0 deletions config/config.toml.default
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ check_float_double = false
check_identifier_upper = false
check_identifier_lower = false
check_read_only = true
# 在MySQL8.0检测是否支持ALGORITHM=INSTANT, 当支持时自动关闭pt-osc/gh-ost.
enable_ddl_instant = true

# 是否检查字段存在多个索引,比如索引 (a,b) 与索引 (a) 中,a字段就是被重复索引的,应当只保留索引 (a,b)
check_index_column_repeat = false
Expand Down
133 changes: 119 additions & 14 deletions session/session_inception.go
Original file line number Diff line number Diff line change
Expand Up @@ -3425,13 +3425,13 @@ func (s *session) checkAlterTable(node *ast.AlterTableStmt, sql string, mergeOnl

// 设置osc开关
s.checkAlterUseOsc(table)
s.checkDDLInstant(node, table)

// 如果修改了表名,则调整回滚语句
hasRenameTable := false
for _, alter := range node.Specs {
if alter.Tp == ast.AlterTableRenameTable {
hasRenameTable = true
s.myRecord.useOsc = false
break
}
}
Expand Down Expand Up @@ -3494,6 +3494,7 @@ func (s *session) checkAlterTable(node *ast.AlterTableStmt, sql string, mergeOnl
s.appendErrorNo(ER_NOT_SUPPORTED_YET)
return
}

for i, alter := range node.Specs {
switch alter.Tp {
case ast.AlterTableOption:
Expand Down Expand Up @@ -3681,6 +3682,123 @@ func (s *session) checkAlterTable(node *ast.AlterTableStmt, sql string, mergeOnl
}
}

// checkDDLInstant 检查是否支持 ALGORITHM=INSTANT, 当支持时自动关闭pt-osc/gh-ost.
func (s *session) checkDDLInstant(node *ast.AlterTableStmt, t *TableInfo) {
if !s.inc.EnableDDLInstant || !s.myRecord.useOsc || s.dbVersion < 50700 {
return
}

if s.dbVersion < 80000 {
// 如果mysql版本小于8.0,只有VIRTUAL column支持Only Modifies Metadata
for _, alter := range node.Specs {
switch alter.Tp {
case ast.AlterTableAddColumns:
newColumns := len(alter.NewColumns)
virtualColumns := 0
for _, nc := range alter.NewColumns {
isPrimary := false
isUnique := false
var isStore *bool
for _, op := range nc.Options {
switch op.Tp {
case ast.ColumnOptionPrimaryKey:
isPrimary = true
case ast.ColumnOptionUniqKey:
isUnique = true
case ast.ColumnOptionGenerated:
isStore = &op.Stored
}
}

if !isPrimary && !isUnique {
if s.dbVersion < 80000 && isStore != nil && !*isStore {
virtualColumns++
}
}
}
if virtualColumns == newColumns {
s.myRecord.useOsc = false
return
}
default:
return
}
}
return
}

canInstantSpecs := 0
for _, alter := range node.Specs {
// 当用户指定了 ALGORITHM=INSTANT 时,忽略检查并关闭osc
if alter.Algorithm == ast.AlgorithmTypeInstant {
s.myRecord.useOsc = false
return
}
switch alter.Tp {
case ast.AlterTableAddColumns:
newColumns := len(alter.NewColumns)
virtualColumns := 0
for _, nc := range alter.NewColumns {
isPrimary := false
isUnique := false
var isStore *bool
for _, op := range nc.Options {
switch op.Tp {
case ast.ColumnOptionPrimaryKey:
isPrimary = true
case ast.ColumnOptionUniqKey:
isUnique = true
case ast.ColumnOptionGenerated:
isStore = &op.Stored
}
}

if !isPrimary && !isUnique {
// 此时已经排除主键/唯一键的情况
// 8.0版本下只有STORED column不支持Only Modifies Metadata
if isStore == nil || !*isStore {
virtualColumns++
}
}
}
if alter.Position.Tp != ast.ColumnPositionNone {
if s.dbVersion < 80029 {
return
} else {
canInstantSpecs++
}
}
if virtualColumns == newColumns {
canInstantSpecs++
} else {
return
}

case ast.AlterTableDropColumn:
for _, field := range t.Fields {
if strings.EqualFold(field.Field, alter.OldColumnName.Name.O) && !field.IsDeleted {
if strings.Contains(field.Extra, "VIRTUAL") {
canInstantSpecs++
}
break
}
}

case ast.AlterTableRenameTable:
canInstantSpecs++

case ast.AlterTableAlterColumn:
canInstantSpecs++

default:
return
}
}
if canInstantSpecs == len(node.Specs) {
s.myRecord.useOsc = false
}
}

func (s *session) checkMultiPartitionParts(specs []*ast.AlterTableSpec) {
if len(specs) <= 1 {
return
Expand Down Expand Up @@ -4973,15 +5091,12 @@ func (s *session) checkAddColumn(t *TableInfo, c *ast.AlterTableSpec) {
if !s.hasError() {
isPrimary := false
isUnique := false
var isStore *bool
for _, op := range nc.Options {
switch op.Tp {
case ast.ColumnOptionPrimaryKey:
isPrimary = true
case ast.ColumnOptionUniqKey:
isUnique = true
case ast.ColumnOptionGenerated:
isStore = &op.Stored
}
}

Expand Down Expand Up @@ -5031,16 +5146,6 @@ func (s *session) checkAddColumn(t *TableInfo, c *ast.AlterTableSpec) {
}
t.Indexes = append(t.Indexes, index)
}
} else {
// 此时已经排除主键/唯一键的情况
// 8.0版本下只有STORED column不支持Only Modifies Metadata
if s.dbVersion >= 80000 && (nil == isStore || !*isStore) {
s.myRecord.useOsc = false
}
// 如果mysql版本小于8.0,只有VIRTUAL column支持Only Modifies Metadata
if s.dbVersion < 80000 && nil != isStore && !*isStore {
s.myRecord.useOsc = false
}
}
}

Expand Down

0 comments on commit 4cffeba

Please sign in to comment.