github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/tests/dailytest/job.go (about)

     1  // Copyright 2020 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dailytest
    15  
    16  import (
    17  	"database/sql"
    18  	"fmt"
    19  
    20  	"github.com/pingcap/errors"
    21  	"github.com/pingcap/log"
    22  	"github.com/pingcap/parser/mysql"
    23  	"github.com/pingcap/tidb/types"
    24  )
    25  
    26  func addJobs(jobCount int, jobChan chan struct{}) {
    27  	for i := 0; i < jobCount; i++ {
    28  		jobChan <- struct{}{}
    29  	}
    30  
    31  	close(jobChan)
    32  }
    33  
    34  func doSqls(table *table, db *sql.DB, count int) {
    35  	var sqls []string
    36  	var args [][]interface{}
    37  	var err error
    38  
    39  	sql, arg, err := genDeleteSqls(table, db, count/10)
    40  	if err != nil {
    41  		log.S().Error(errors.ErrorStack(err))
    42  	} else {
    43  		sqls = append(sqls, sql...)
    44  		args = append(args, arg...)
    45  	}
    46  
    47  	sql, arg, err = genInsertSqls(table, count)
    48  	if err != nil {
    49  		log.S().Error(errors.ErrorStack(err))
    50  	} else {
    51  		sqls = append(sqls, sql...)
    52  		args = append(args, arg...)
    53  	}
    54  
    55  	sql, arg, err = genUpdateSqls(table, db, count/10)
    56  	if err != nil {
    57  		log.S().Error(errors.ErrorStack(err))
    58  	} else {
    59  		sqls = append(sqls, sql...)
    60  		args = append(args, arg...)
    61  	}
    62  
    63  	execSqls(db, sqls, args)
    64  }
    65  
    66  func execSqls(db *sql.DB, sqls []string, args [][]interface{}) {
    67  	txn, err := db.Begin()
    68  	if err != nil {
    69  		log.S().Fatalf(errors.ErrorStack(err))
    70  	}
    71  
    72  	for i := range sqls {
    73  		_, err = txn.Exec(sqls[i], args[i]...)
    74  		if err != nil {
    75  			log.S().Error(errors.ErrorStack(err))
    76  		}
    77  	}
    78  
    79  	err = txn.Commit()
    80  	if err != nil {
    81  		log.S().Warn(errors.ErrorStack(err))
    82  	}
    83  }
    84  
    85  func doJob(table *table, db *sql.DB, batch int, jobChan chan struct{}, doneChan chan struct{}) {
    86  	count := 0
    87  	for range jobChan {
    88  		count++
    89  		if count == batch {
    90  			doSqls(table, db, count)
    91  			count = 0
    92  		}
    93  	}
    94  
    95  	if count > 0 {
    96  		doSqls(table, db, count)
    97  	}
    98  
    99  	doneChan <- struct{}{}
   100  }
   101  
   102  func doWait(doneChan chan struct{}, workerCount int) {
   103  	for i := 0; i < workerCount; i++ {
   104  		<-doneChan
   105  	}
   106  
   107  	close(doneChan)
   108  }
   109  
   110  func doDMLProcess(table *table, db *sql.DB, jobCount int, workerCount int, batch int) {
   111  	jobChan := make(chan struct{}, 16*workerCount)
   112  	doneChan := make(chan struct{}, workerCount)
   113  
   114  	go addJobs(jobCount, jobChan)
   115  
   116  	for i := 0; i < workerCount; i++ {
   117  		go doJob(table, db, batch, jobChan, doneChan)
   118  	}
   119  
   120  	doWait(doneChan, workerCount)
   121  }
   122  
   123  func doDDLProcess(table *table, db *sql.DB) {
   124  	// do drop column ddl
   125  	index := randInt(2, len(table.columns)-1)
   126  	col := table.columns[index]
   127  
   128  	_, ok1 := table.indices[col.name]
   129  	_, ok2 := table.uniqIndices[col.name]
   130  	if !ok1 && !ok2 {
   131  		newCols := make([]*column, 0, len(table.columns)-1)
   132  		newCols = append(newCols, table.columns[:index]...)
   133  		newCols = append(newCols, table.columns[index+1:]...)
   134  		table.columns = newCols
   135  		sql := fmt.Sprintf("alter table %s drop column %s", table.name, col.name)
   136  		execSqls(db, []string{sql}, [][]interface{}{{}})
   137  	}
   138  
   139  	// do add  column ddl
   140  	index = randInt(2, len(table.columns)-1)
   141  	colName := randString(5)
   142  
   143  	col = &column{
   144  		name: colName,
   145  		tp: &types.FieldType{
   146  			Tp:   mysql.TypeVarchar,
   147  			Flen: 45,
   148  		},
   149  	}
   150  
   151  	newCols := make([]*column, 0, len(table.columns)+1)
   152  	newCols = append(newCols, table.columns[:index]...)
   153  	newCols = append(newCols, col)
   154  	newCols = append(newCols, table.columns[index:]...)
   155  
   156  	table.columns = newCols
   157  	sql := fmt.Sprintf("alter table %s add column `%s` varchar(45) after %s", table.name, col.name, table.columns[index-1].name)
   158  	execSqls(db, []string{sql}, [][]interface{}{{}})
   159  }
   160  
   161  func doProcess(table *table, db *sql.DB, jobCount int, workerCount int, batch int) {
   162  	if len(table.columns) <= 2 {
   163  		log.S().Fatal("column count must > 2, and the first and second column are for primary key")
   164  	}
   165  
   166  	doDMLProcess(table, db, jobCount/2, workerCount, batch)
   167  	doDDLProcess(table, db)
   168  	doDMLProcess(table, db, jobCount/2, workerCount, batch)
   169  }