Skip to content

Commit 59d0670

Browse files
authored
Classify deadlock avoided for CH ALTER as recoverable (#4418)
Closes DBI-799
1 parent f07ac54 commit 59d0670

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

flow/alerting/classifier.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ var (
6464
ClickHouseObjectStorageIOErrorRe = regexp.MustCompile(
6565
`unspecified iostream_category error: while reading .+: While executing ReadFromObjectStorage`,
6666
)
67-
PostgresPublicationDoesNotExistRe = regexp.MustCompile(`publication ".*?" does not exist`)
68-
PostgresSnapshotDoesNotExistRe = regexp.MustCompile(`snapshot ".*?" does not exist`)
69-
PostgresWalSegmentRemovedRe = regexp.MustCompile(`requested WAL segment \w+ has already been removed`)
70-
PostgresSpillFileMissingRe = regexp.MustCompile(`Unable to restore changes for xid \d+`)
67+
ClickHouseLockingAttemptForAlterRe = regexp.MustCompile(`Locking attempt for ALTER on .+ has timed out`)
68+
PostgresPublicationDoesNotExistRe = regexp.MustCompile(`publication ".*?" does not exist`)
69+
PostgresSnapshotDoesNotExistRe = regexp.MustCompile(`snapshot ".*?" does not exist`)
70+
PostgresWalSegmentRemovedRe = regexp.MustCompile(`requested WAL segment \w+ has already been removed`)
71+
PostgresSpillFileMissingRe = regexp.MustCompile(`Unable to restore changes for xid \d+`)
7172
// e.g. could not rename file "pg_logical/snapshots/25-3370F40.snap.19943.tmp" to "pg_logical/snapshots/25-3370F40.snap"
7273
PostgresCouldNotRenameSnapshotRe = regexp.MustCompile(`could not rename file ".*\.snap\..*\.tmp" to ".*\.snap"`)
7374
MySqlRdsBinlogFileNotFoundRe = regexp.MustCompile(`File '/rdsdbdata/log/binlog/mysql-bin-changelog.\d+' not found`)
@@ -956,6 +957,10 @@ func GetErrorClass(ctx context.Context, err error) (ErrorClass, ErrorInfo) {
956957
return ErrorRetryRecoverable, chErrorInfo
957958
case chproto.ErrCannotAssignAlter:
958959
return ErrorNotifyClickHouseError, chErrorInfo
960+
case chproto.ErrDeadlockAvoided:
961+
if ClickHouseLockingAttemptForAlterRe.MatchString(chException.Message) {
962+
return ErrorRetryRecoverable, chErrorInfo
963+
}
959964
case chproto.ErrAborted:
960965
return ErrorInternalClickHouse, chErrorInfo
961966
case chproto.ErrTooManySimultaneousQueries:

flow/alerting/classifier_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,21 @@ func TestClickHouseOtherUnfinishedShouldBeRecoverable(t *testing.T) {
951951
}, errInfo)
952952
}
953953

954+
func TestClickHouseLockingAttemptForAlterTimedOutShouldBeRecoverable(t *testing.T) {
955+
err := &clickhouse.Exception{
956+
Code: int32(chproto.ErrDeadlockAvoided),
957+
//nolint:lll
958+
Message: `Locking attempt for ALTER on "my_database.my_table" has timed out! (120000 ms) Possible deadlock avoided. Client should retry.`,
959+
}
960+
errorClass, errInfo := GetErrorClass(t.Context(), fmt.Errorf(
961+
"failed to push records: failed to sync schema changes: failed to add column case_number for table my_table: %w", err))
962+
assert.Equal(t, ErrorRetryRecoverable, errorClass, "Unexpected error class")
963+
assert.Equal(t, ErrorInfo{
964+
Source: ErrorSourceClickHouse,
965+
Code: strconv.Itoa(int(chproto.ErrDeadlockAvoided)),
966+
}, errInfo, "Unexpected error info")
967+
}
968+
954969
func TestMySQLUnsupportedDDLShouldNotifyUser(t *testing.T) {
955970
err := exceptions.NewMySQLUnsupportedDDLError("test_db.test_table")
956971
errorClass, errInfo := GetErrorClass(t.Context(), fmt.Errorf("mysql error: %w", err))

0 commit comments

Comments
 (0)