Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: optimize mysql v8.0 ddl instant check (#668) #673

Merged
merged 1 commit into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,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 @@ -703,6 +705,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 @@ -3354,13 +3354,13 @@

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

Check warning on line 3357 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3357

Added line #L3357 was not covered by tests

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

for i, alter := range node.Specs {
switch alter.Tp {
case ast.AlterTableOption:
Expand Down Expand Up @@ -3610,6 +3611,123 @@
}
}

// 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

Check warning on line 3617 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3615-L3617

Added lines #L3615 - L3617 were not covered by tests
}

if s.dbVersion < 80000 {

Check warning on line 3620 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3620

Added line #L3620 was not covered by tests
// 如果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

Check warning on line 3638 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3622-L3638

Added lines #L3622 - L3638 were not covered by tests
}
}

if !isPrimary && !isUnique {
if s.dbVersion < 80000 && isStore != nil && !*isStore {
virtualColumns++

Check warning on line 3644 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3642-L3644

Added lines #L3642 - L3644 were not covered by tests
}
}
}
if virtualColumns == newColumns {
s.myRecord.useOsc = false
return

Check warning on line 3650 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3648-L3650

Added lines #L3648 - L3650 were not covered by tests
}
default:
return

Check warning on line 3653 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3652-L3653

Added lines #L3652 - L3653 were not covered by tests
}
}
return

Check warning on line 3656 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3656

Added line #L3656 was not covered by tests
}

canInstantSpecs := 0
for _, alter := range node.Specs {

Check warning on line 3660 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3659-L3660

Added lines #L3659 - L3660 were not covered by tests
// 当用户指定了 ALGORITHM=INSTANT 时,忽略检查并关闭osc
if alter.Algorithm == ast.AlgorithmTypeInstant {
s.myRecord.useOsc = false
return

Check warning on line 3664 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3662-L3664

Added lines #L3662 - L3664 were not covered by tests
}
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

Check warning on line 3681 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3666-L3681

Added lines #L3666 - L3681 were not covered by tests
}
}

if !isPrimary && !isUnique {

Check warning on line 3685 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3685

Added line #L3685 was not covered by tests
// 此时已经排除主键/唯一键的情况
// 8.0版本下只有STORED column不支持Only Modifies Metadata
if isStore == nil || !*isStore {
virtualColumns++

Check warning on line 3689 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3688-L3689

Added lines #L3688 - L3689 were not covered by tests
}
}
}
if alter.Position.Tp != ast.ColumnPositionNone {
if s.dbVersion < 80029 {
return
} else {
canInstantSpecs++

Check warning on line 3697 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3693-L3697

Added lines #L3693 - L3697 were not covered by tests
}
}
if virtualColumns == newColumns {
canInstantSpecs++
} else {
return

Check warning on line 3703 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3700-L3703

Added lines #L3700 - L3703 were not covered by tests
}

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++

Check warning on line 3710 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3706-L3710

Added lines #L3706 - L3710 were not covered by tests
}
break

Check warning on line 3712 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3712

Added line #L3712 was not covered by tests
}
}

case ast.AlterTableRenameTable:
canInstantSpecs++

Check warning on line 3717 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3716-L3717

Added lines #L3716 - L3717 were not covered by tests

case ast.AlterTableAlterColumn:
canInstantSpecs++

Check warning on line 3720 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3719-L3720

Added lines #L3719 - L3720 were not covered by tests

default:
return

Check warning on line 3723 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3722-L3723

Added lines #L3722 - L3723 were not covered by tests
}
}
if canInstantSpecs == len(node.Specs) {
s.myRecord.useOsc = false

Check warning on line 3727 in session/session_inception.go

View check run for this annotation

Codecov / codecov/patch

session/session_inception.go#L3726-L3727

Added lines #L3726 - L3727 were not covered by tests
}
}

func (s *session) checkMultiPartitionParts(specs []*ast.AlterTableSpec) {
if len(specs) <= 1 {
return
Expand Down Expand Up @@ -4902,15 +5020,12 @@
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 @@ -4960,16 +5075,6 @@
}
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
Loading