github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/stochastikctx/variable/session.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 variable 15 16 import ( 17 "bytes" 18 "crypto/tls" 19 "encoding/binary" 20 "fmt" 21 "math" 22 "math/rand" 23 "sort" 24 "strconv" 25 "strings" 26 "sync" 27 "sync/atomic" 28 "time" 29 30 "github.com/klauspost/cpuid" 31 "github.com/twmb/murmur3" 32 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 33 "github.com/whtcorpsinc/BerolinaSQL/ast" 34 "github.com/whtcorpsinc/BerolinaSQL/auth" 35 "github.com/whtcorpsinc/BerolinaSQL/charset" 36 "github.com/whtcorpsinc/BerolinaSQL/terror" 37 "github.com/whtcorpsinc/errors" 38 pumpcli "github.com/whtcorpsinc/milevadb-tools/milevadb-binlog/pump_client" 39 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle" 40 "github.com/whtcorpsinc/milevadb/config" 41 "github.com/whtcorpsinc/milevadb/ekv" 42 "github.com/whtcorpsinc/milevadb/metrics" 43 "github.com/whtcorpsinc/milevadb/soliton/chunk" 44 "github.com/whtcorpsinc/milevadb/soliton/defCauslate" 45 "github.com/whtcorpsinc/milevadb/soliton/execdetails" 46 "github.com/whtcorpsinc/milevadb/soliton/logutil" 47 "github.com/whtcorpsinc/milevadb/soliton/rowcodec" 48 "github.com/whtcorpsinc/milevadb/soliton/storeutil" 49 "github.com/whtcorpsinc/milevadb/soliton/stringutil" 50 "github.com/whtcorpsinc/milevadb/soliton/timeutil" 51 "github.com/whtcorpsinc/milevadb/spacetime/autoid" 52 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 53 "github.com/whtcorpsinc/milevadb/types" 54 ) 55 56 var preparedStmtCount int64 57 58 // RetryInfo saves retry information. 59 type RetryInfo struct { 60 Retrying bool 61 DroppedPreparedStmtIDs []uint32 62 autoIncrementIDs retryInfoAutoIDs 63 autoRandomIDs retryInfoAutoIDs 64 } 65 66 // Clean does some clean work. 67 func (r *RetryInfo) Clean() { 68 r.autoIncrementIDs.clean() 69 r.autoRandomIDs.clean() 70 71 if len(r.DroppedPreparedStmtIDs) > 0 { 72 r.DroppedPreparedStmtIDs = r.DroppedPreparedStmtIDs[:0] 73 } 74 } 75 76 // ResetOffset resets the current retry offset. 77 func (r *RetryInfo) ResetOffset() { 78 r.autoIncrementIDs.resetOffset() 79 r.autoRandomIDs.resetOffset() 80 } 81 82 // AddAutoIncrementID adds id to autoIncrementIDs. 83 func (r *RetryInfo) AddAutoIncrementID(id int64) { 84 r.autoIncrementIDs.autoIDs = append(r.autoIncrementIDs.autoIDs, id) 85 } 86 87 // GetCurrAutoIncrementID gets current autoIncrementID. 88 func (r *RetryInfo) GetCurrAutoIncrementID() (int64, error) { 89 return r.autoIncrementIDs.getCurrent() 90 } 91 92 // AddAutoRandomID adds id to autoRandomIDs. 93 func (r *RetryInfo) AddAutoRandomID(id int64) { 94 r.autoRandomIDs.autoIDs = append(r.autoRandomIDs.autoIDs, id) 95 } 96 97 // GetCurrAutoRandomID gets current AutoRandomID. 98 func (r *RetryInfo) GetCurrAutoRandomID() (int64, error) { 99 return r.autoRandomIDs.getCurrent() 100 } 101 102 type retryInfoAutoIDs struct { 103 currentOffset int 104 autoIDs []int64 105 } 106 107 func (r *retryInfoAutoIDs) resetOffset() { 108 r.currentOffset = 0 109 } 110 111 func (r *retryInfoAutoIDs) clean() { 112 r.currentOffset = 0 113 if len(r.autoIDs) > 0 { 114 r.autoIDs = r.autoIDs[:0] 115 } 116 } 117 118 func (r *retryInfoAutoIDs) getCurrent() (int64, error) { 119 if r.currentOffset >= len(r.autoIDs) { 120 return 0, errCantGetValidID 121 } 122 id := r.autoIDs[r.currentOffset] 123 r.currentOffset++ 124 return id, nil 125 } 126 127 // stmtFuture is used to async get timestamp for memex. 128 type stmtFuture struct { 129 future oracle.Future 130 cachedTS uint64 131 } 132 133 // TransactionContext is used to causetstore variables that has transaction scope. 134 type TransactionContext struct { 135 forUFIDelateTS uint64 136 stmtFuture oracle.Future 137 Binlog interface{} 138 SchemaReplicant interface{} 139 History interface{} 140 SchemaVersion int64 141 StartTS uint64 142 143 // ShardStep indicates the max size of continuous rowid shard in one transaction. 144 ShardStep int 145 shardRemain int 146 currentShard int64 147 shardRand *rand.Rand 148 149 // BlockDeltaMap is used in the schemaReplicant validator for DBS changes in one causet not to causet others. 150 // It's also used in the statistias uFIDelating. 151 // Note: for the partitionted causet, it stores all the partition IDs. 152 BlockDeltaMap map[int64]BlockDelta 153 154 // unchangedRowKeys is used to causetstore the unchanged rows that needs to dagger for pessimistic transaction. 155 unchangedRowKeys map[string]struct{} 156 157 // pessimisticLockCache is the cache for pessimistic locked keys, 158 // The value never changes during the transaction. 159 pessimisticLockCache map[string][]byte 160 PessimisticCacheHit int 161 162 // CreateTime For metrics. 163 CreateTime time.Time 164 StatementCount int 165 CouldRetry bool 166 IsPessimistic bool 167 Isolation string 168 LockExpire uint32 169 ForUFIDelate uint32 170 } 171 172 // GetShard returns the shard prefix for the next `count` rowids. 173 func (tc *TransactionContext) GetShard(shardRowIDBits uint64, typeBitsLength uint64, reserveSignBit bool, count int) int64 { 174 if shardRowIDBits == 0 { 175 return 0 176 } 177 if tc.shardRand == nil { 178 tc.shardRand = rand.New(rand.NewSource(int64(tc.StartTS))) 179 } 180 if tc.shardRemain <= 0 { 181 tc.uFIDelateShard() 182 tc.shardRemain = tc.ShardStep 183 } 184 tc.shardRemain -= count 185 186 var signBitLength uint64 187 if reserveSignBit { 188 signBitLength = 1 189 } 190 return (tc.currentShard & (1<<shardRowIDBits - 1)) << (typeBitsLength - shardRowIDBits - signBitLength) 191 } 192 193 func (tc *TransactionContext) uFIDelateShard() { 194 var buf [8]byte 195 binary.LittleEndian.PutUint64(buf[:], tc.shardRand.Uint64()) 196 tc.currentShard = int64(murmur3.Sum32(buf[:])) 197 } 198 199 // AddUnchangedRowKey adds an unchanged event key in uFIDelate memex for pessimistic dagger. 200 func (tc *TransactionContext) AddUnchangedRowKey(key []byte) { 201 if tc.unchangedRowKeys == nil { 202 tc.unchangedRowKeys = map[string]struct{}{} 203 } 204 tc.unchangedRowKeys[string(key)] = struct{}{} 205 } 206 207 // DefCauslectUnchangedRowKeys defCauslects unchanged event keys for pessimistic dagger. 208 func (tc *TransactionContext) DefCauslectUnchangedRowKeys(buf []ekv.Key) []ekv.Key { 209 for key := range tc.unchangedRowKeys { 210 buf = append(buf, ekv.Key(key)) 211 } 212 tc.unchangedRowKeys = nil 213 return buf 214 } 215 216 // UFIDelateDeltaForBlock uFIDelates the delta info for some causet. 217 func (tc *TransactionContext) UFIDelateDeltaForBlock(physicalBlockID int64, delta int64, count int64, defCausSize map[int64]int64) { 218 if tc.BlockDeltaMap == nil { 219 tc.BlockDeltaMap = make(map[int64]BlockDelta) 220 } 221 item := tc.BlockDeltaMap[physicalBlockID] 222 if item.DefCausSize == nil && defCausSize != nil { 223 item.DefCausSize = make(map[int64]int64, len(defCausSize)) 224 } 225 item.Delta += delta 226 item.Count += count 227 for key, val := range defCausSize { 228 item.DefCausSize[key] += val 229 } 230 tc.BlockDeltaMap[physicalBlockID] = item 231 } 232 233 // GetKeyInPessimisticLockCache gets a key in pessimistic dagger cache. 234 func (tc *TransactionContext) GetKeyInPessimisticLockCache(key ekv.Key) (val []byte, ok bool) { 235 if tc.pessimisticLockCache == nil { 236 return nil, false 237 } 238 val, ok = tc.pessimisticLockCache[string(key)] 239 if ok { 240 tc.PessimisticCacheHit++ 241 } 242 return 243 } 244 245 // SetPessimisticLockCache sets a key value pair into pessimistic dagger cache. 246 func (tc *TransactionContext) SetPessimisticLockCache(key ekv.Key, val []byte) { 247 if tc.pessimisticLockCache == nil { 248 tc.pessimisticLockCache = map[string][]byte{} 249 } 250 tc.pessimisticLockCache[string(key)] = val 251 } 252 253 // Cleanup clears up transaction info that no longer use. 254 func (tc *TransactionContext) Cleanup() { 255 // tc.SchemaReplicant = nil; we cannot do it now, because some operation like handleFieldList depend on this. 256 tc.Binlog = nil 257 tc.History = nil 258 tc.BlockDeltaMap = nil 259 tc.pessimisticLockCache = nil 260 } 261 262 // ClearDelta clears the delta map. 263 func (tc *TransactionContext) ClearDelta() { 264 tc.BlockDeltaMap = nil 265 } 266 267 // GetForUFIDelateTS returns the ts for uFIDelate. 268 func (tc *TransactionContext) GetForUFIDelateTS() uint64 { 269 if tc.forUFIDelateTS > tc.StartTS { 270 return tc.forUFIDelateTS 271 } 272 return tc.StartTS 273 } 274 275 // SetForUFIDelateTS sets the ts for uFIDelate. 276 func (tc *TransactionContext) SetForUFIDelateTS(forUFIDelateTS uint64) { 277 if forUFIDelateTS > tc.forUFIDelateTS { 278 tc.forUFIDelateTS = forUFIDelateTS 279 } 280 } 281 282 // SetStmtFutureForRC sets the stmtFuture . 283 func (tc *TransactionContext) SetStmtFutureForRC(future oracle.Future) { 284 tc.stmtFuture = future 285 } 286 287 // GetStmtFutureForRC gets the stmtFuture. 288 func (tc *TransactionContext) GetStmtFutureForRC() oracle.Future { 289 return tc.stmtFuture 290 } 291 292 // WriteStmtBufs can be used by insert/replace/delete/uFIDelate memex. 293 // TODO: use a common memory pool to replace this. 294 type WriteStmtBufs struct { 295 // RowValBuf is used by blockcodec.EncodeRow, to reduce runtime.growslice. 296 RowValBuf []byte 297 // AddRowValues use to causetstore temp insert rows value, to reduce memory allocations when importing data. 298 AddRowValues []types.Causet 299 300 // IndexValsBuf is used by index.FetchValues 301 IndexValsBuf []types.Causet 302 // IndexKeyBuf is used by index.GenIndexKey 303 IndexKeyBuf []byte 304 } 305 306 func (ib *WriteStmtBufs) clean() { 307 ib.RowValBuf = nil 308 ib.AddRowValues = nil 309 ib.IndexValsBuf = nil 310 ib.IndexKeyBuf = nil 311 } 312 313 // BlockSnapshot represents a data snapshot of the causet contained in `information_schema`. 314 type BlockSnapshot struct { 315 Rows [][]types.Causet 316 Err error 317 } 318 319 type txnIsolationLevelOneShotState uint 320 321 // RewritePhaseInfo records some information about the rewrite phase 322 type RewritePhaseInfo struct { 323 // DurationRewrite is the duration of rewriting the ALLEGROALLEGROSQL. 324 DurationRewrite time.Duration 325 326 // DurationPreprocessSubQuery is the duration of pre-processing sub-queries. 327 DurationPreprocessSubQuery time.Duration 328 329 // PreprocessSubQueries is the number of pre-processed sub-queries. 330 PreprocessSubQueries int 331 } 332 333 // Reset resets all fields in RewritePhaseInfo. 334 func (r *RewritePhaseInfo) Reset() { 335 r.DurationRewrite = 0 336 r.DurationPreprocessSubQuery = 0 337 r.PreprocessSubQueries = 0 338 } 339 340 const ( 341 // oneShotDef means default, that is tx_isolation_one_shot not set. 342 oneShotDef txnIsolationLevelOneShotState = iota 343 // oneShotSet means it's set in current transaction. 344 oneShotSet 345 // onsShotUse means it should be used in current transaction. 346 oneShotUse 347 ) 348 349 // StochastikVars is to handle user-defined or global variables in the current stochastik. 350 type StochastikVars struct { 351 Concurrency 352 MemQuota 353 BatchSize 354 // DMLBatchSize indicates the number of rows batch-committed for a memex. 355 // It will be used when using LOAD DATA or BatchInsert or BatchDelete is on. 356 DMLBatchSize int 357 RetryLimit int64 358 DisableTxnAutoRetry bool 359 // UsersLock is a dagger for user defined variables. 360 UsersLock sync.RWMutex 361 // Users are user defined variables. 362 Users map[string]types.Causet 363 // systems variables, don't modify it directly, use GetSystemVar/SetSystemVar method. 364 systems map[string]string 365 // SysWarningCount is the system variable "warning_count", because it is on the hot path, so we extract it from the systems 366 SysWarningCount int 367 // SysErrorCount is the system variable "error_count", because it is on the hot path, so we extract it from the systems 368 SysErrorCount uint16 369 // PreparedStmts stores prepared memex. 370 PreparedStmts map[uint32]interface{} 371 PreparedStmtNameToID map[string]uint32 372 // preparedStmtID is id of prepared memex. 373 preparedStmtID uint32 374 // PreparedParams params for prepared memexs 375 PreparedParams PreparedParams 376 377 // ActiveRoles stores active roles for current user 378 ActiveRoles []*auth.RoleIdentity 379 380 RetryInfo *RetryInfo 381 // TxnCtx Should be reset on transaction finished. 382 TxnCtx *TransactionContext 383 384 // KVVars is the variables for KV storage. 385 KVVars *ekv.Variables 386 387 // txnIsolationLevelOneShot is used to implements "set transaction isolation level ..." 388 txnIsolationLevelOneShot struct { 389 state txnIsolationLevelOneShotState 390 value string 391 } 392 393 // Status stands for the stochastik status. e.g. in transaction or not, auto commit is on or off, and so on. 394 Status uint16 395 396 // ClientCapability is client's capability. 397 ClientCapability uint32 398 399 // TLSConnectionState is the TLS connection state (nil if not using TLS). 400 TLSConnectionState *tls.ConnectionState 401 402 // ConnectionID is the connection id of the current stochastik. 403 ConnectionID uint64 404 405 // CausetID is the unique id of logical and physical plan. 406 CausetID int 407 408 // CausetDeferredCausetID is the unique id for defCausumn when building plan. 409 CausetDeferredCausetID int64 410 411 // User is the user identity with which the stochastik login. 412 User *auth.UserIdentity 413 414 // CurrentDB is the default database of this stochastik. 415 CurrentDB string 416 417 // CurrentDBChanged indicates if the CurrentDB has been uFIDelated, and if it is we should print it into 418 // the slow log to make it be compatible with MyALLEGROSQL, https://github.com/whtcorpsinc/milevadb/issues/17846. 419 CurrentDBChanged bool 420 421 // StrictALLEGROSQLMode indicates if the stochastik is in strict mode. 422 StrictALLEGROSQLMode bool 423 424 // CommonGlobalLoaded indicates if common global variable has been loaded for this stochastik. 425 CommonGlobalLoaded bool 426 427 // InRestrictedALLEGROSQL indicates if the stochastik is handling restricted ALLEGROALLEGROSQL execution. 428 InRestrictedALLEGROSQL bool 429 430 // SnapshotTS is used for reading history data. For simplicity, SnapshotTS only supports allegrosql request. 431 SnapshotTS uint64 432 433 // SnapshotschemaReplicant is used with SnapshotTS, when the schemaReplicant version at snapshotTS less than current schemaReplicant 434 // version, we load an old version schemaReplicant for query. 435 SnapshotschemaReplicant interface{} 436 437 // BinlogClient is used to write binlog. 438 BinlogClient *pumpcli.PumpsClient 439 440 // GlobalVarsAccessor is used to set and get global variables. 441 GlobalVarsAccessor GlobalVarAccessor 442 443 // LastFoundRows is the number of found rows of last query memex 444 LastFoundRows uint64 445 446 // StmtCtx holds variables for current executing memex. 447 StmtCtx *stmtctx.StatementContext 448 449 // AllowAggPushDown can be set to false to forbid aggregation push down. 450 AllowAggPushDown bool 451 452 // AllowBCJ means allow broadcast join. 453 AllowBCJ bool 454 // AllowDistinctAggPushDown can be set true to allow agg with distinct push down to einsteindb/tiflash. 455 AllowDistinctAggPushDown bool 456 457 // AllowWriteRowID can be set to false to forbid write data to _milevadb_rowid. 458 // This variable is currently not recommended to be turned on. 459 AllowWriteRowID bool 460 461 // AllowBatchCop means if we should send batch interlock to TiFlash. Default value is 1, means to use batch cop in case of aggregation and join. 462 // If value is set to 2 , which means to force to send batch cop for any query. Value is set to 0 means never use batch cop. 463 AllowBatchCop int 464 465 // MilevaDBAllowAutoRandExplicitInsert indicates whether explicit insertion on auto_random defCausumn is allowed. 466 AllowAutoRandExplicitInsert bool 467 468 // CorrelationThreshold is the guard to enable event count estimation using defCausumn order correlation. 469 CorrelationThreshold float64 470 471 // CorrelationExpFactor is used to control the heuristic approach of event count estimation when CorrelationThreshold is not met. 472 CorrelationExpFactor int 473 474 // CPUFactor is the CPU cost of processing one memex for one event. 475 CPUFactor float64 476 // CopCPUFactor is the CPU cost of processing one memex for one event in interlock. 477 CopCPUFactor float64 478 // CopTiFlashConcurrencyFactor is the concurrency number of computation in tiflash interlock. 479 CopTiFlashConcurrencyFactor float64 480 // NetworkFactor is the network cost of transferring 1 byte data. 481 NetworkFactor float64 482 // ScanFactor is the IO cost of scanning 1 byte data on EinsteinDB and TiFlash. 483 ScanFactor float64 484 // DescScanFactor is the IO cost of scanning 1 byte data on EinsteinDB and TiFlash in desc order. 485 DescScanFactor float64 486 // SeekFactor is the IO cost of seeking the start value of a range in EinsteinDB or TiFlash. 487 SeekFactor float64 488 // MemoryFactor is the memory cost of storing one tuple. 489 MemoryFactor float64 490 // DiskFactor is the IO cost of reading/writing one byte to temporary disk. 491 DiskFactor float64 492 // ConcurrencyFactor is the CPU cost of additional one goroutine. 493 ConcurrencyFactor float64 494 495 // CurrInsertValues is used to record current ValuesExpr's values. 496 // See http://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values 497 CurrInsertValues chunk.Row 498 499 // Per-connection time zones. Each client that connects has its own time zone setting, given by the stochastik time_zone variable. 500 // See https://dev.allegrosql.com/doc/refman/5.7/en/time-zone-support.html 501 TimeZone *time.Location 502 503 ALLEGROSQLMode allegrosql.ALLEGROSQLMode 504 505 // AutoIncrementIncrement and AutoIncrementOffset indicates the autoID's start value and increment. 506 AutoIncrementIncrement int 507 508 AutoIncrementOffset int 509 510 /* MilevaDB system variables */ 511 512 // SkipASCIICheck check on input value. 513 SkipASCIICheck bool 514 515 // SkipUTF8Check check on input value. 516 SkipUTF8Check bool 517 518 // BatchInsert indicates if we should split insert data into multiple batches. 519 BatchInsert bool 520 521 // BatchDelete indicates if we should split delete data into multiple batches. 522 BatchDelete bool 523 524 // BatchCommit indicates if we should split the transaction into multiple batches. 525 BatchCommit bool 526 527 // IDSlabPredictor is provided by ekvCausetEncoder, if it is provided, we will use it to alloc auto id instead of using 528 // Block.alloc. 529 IDSlabPredictor autoid.SlabPredictor 530 531 // OptimizerSelectivityLevel defines the level of the selectivity estimation in plan. 532 OptimizerSelectivityLevel int 533 534 // EnableBlockPartition enables causet partition feature. 535 EnableBlockPartition string 536 537 // EnableCascadesCausetAppend enables the cascades causet. 538 EnableCascadesCausetAppend bool 539 540 // EnableWindowFunction enables the window function. 541 EnableWindowFunction bool 542 543 // EnableVectorizedExpression enables the vectorized memex evaluation. 544 EnableVectorizedExpression bool 545 546 // DBSReorgPriority is the operation priority of adding indices. 547 DBSReorgPriority int 548 549 // EnableChangeDeferredCausetType is used to control whether to enable the change defCausumn type. 550 EnableChangeDeferredCausetType bool 551 552 // WaitSplitRegionFinish defines the split region behaviour is sync or async. 553 WaitSplitRegionFinish bool 554 555 // WaitSplitRegionTimeout defines the split region timeout. 556 WaitSplitRegionTimeout uint64 557 558 // EnableStreaming indicates whether the interlock request can use streaming API. 559 // TODO: remove this after milevadb-server configuration "enable-streaming' removed. 560 EnableStreaming bool 561 562 // EnableChunkRPC indicates whether the interlock request can use chunk API. 563 EnableChunkRPC bool 564 565 writeStmtBufs WriteStmtBufs 566 567 // L2CacheSize indicates the size of CPU L2 cache, using byte as unit. 568 L2CacheSize int 569 570 // EnableRadixJoin indicates whether to use radix hash join to execute 571 // HashJoin. 572 EnableRadixJoin bool 573 574 // ConstraintCheckInPlace indicates whether to check the constraint when the ALLEGROALLEGROSQL executing. 575 ConstraintCheckInPlace bool 576 577 // CommandValue indicates which command current stochastik is doing. 578 CommandValue uint32 579 580 // MilevaDBOptJoinReorderThreshold defines the minimal number of join nodes 581 // to use the greedy join reorder algorithm. 582 MilevaDBOptJoinReorderThreshold int 583 584 // SlowQueryFile indicates which slow query log file for SLOW_QUERY causet to parse. 585 SlowQueryFile string 586 587 // EnableFastAnalyze indicates whether to take fast analyze. 588 EnableFastAnalyze bool 589 590 // TxnMode indicates should be pessimistic or optimistic. 591 TxnMode string 592 593 // LowResolutionTSO is used for reading data with low resolution TSO which is uFIDelated once every two seconds. 594 LowResolutionTSO bool 595 596 // MaxInterDircutionTime is the timeout for select memex, in milliseconds. 597 // If the value is 0, timeouts are not enabled. 598 // See https://dev.allegrosql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_execution_time 599 MaxInterDircutionTime uint64 600 601 // Killed is a flag to indicate that this query is killed. 602 Killed uint32 603 604 // ConnectionInfo indicates current connection info used by current stochastik, only be lazy assigned by plugin. 605 ConnectionInfo *ConnectionInfo 606 607 // use noop funcs or not 608 EnableNoopFuncs bool 609 610 // StartTime is the start time of the last query. 611 StartTime time.Time 612 613 // DurationParse is the duration of parsing ALLEGROALLEGROSQL string to AST of the last query. 614 DurationParse time.Duration 615 616 // DurationCompile is the duration of compiling AST to execution plan of the last query. 617 DurationCompile time.Duration 618 619 // RewritePhaseInfo records all information about the rewriting phase. 620 RewritePhaseInfo 621 622 // DurationOptimization is the duration of optimizing a query. 623 DurationOptimization time.Duration 624 625 // DurationWaitTS is the duration of waiting for a snapshot TS 626 DurationWaitTS time.Duration 627 628 // PrevStmt is used to causetstore the previous executed memex in the current stochastik. 629 PrevStmt fmt.Stringer 630 631 // prevStmtDigest is used to causetstore the digest of the previous memex in the current stochastik. 632 prevStmtDigest string 633 634 // AllowRemoveAutoInc indicates whether a user can drop the auto_increment defCausumn attribute or not. 635 AllowRemoveAutoInc bool 636 637 // UseCausetBaselines indicates whether we will use plan baselines to adjust plan. 638 UseCausetBaselines bool 639 640 // EvolveCausetBaselines indicates whether we will evolve the plan baselines. 641 EvolveCausetBaselines bool 642 643 // Unexported fields should be accessed and set through interfaces like GetReplicaRead() and SetReplicaRead(). 644 645 // allowInSubqToJoinAnPosetDagg can be set to false to forbid rewriting the semi join to inner join with agg. 646 allowInSubqToJoinAnPosetDagg bool 647 648 // EnableIndexMerge enables the generation of IndexMergePath. 649 enableIndexMerge bool 650 651 // replicaRead is used for reading data from replicas, only follower is supported at this time. 652 replicaRead ekv.ReplicaReadType 653 654 // IsolationReadEngines is used to isolation read, milevadb only read from the stores whose engine type is in the engines. 655 IsolationReadEngines map[ekv.StoreType]struct{} 656 657 CausetAppendSelectBlockAsName []ast.HintBlock 658 659 // LockWaitTimeout is the duration waiting for pessimistic dagger in milliseconds 660 // negative value means nowait, 0 means default behavior, others means actual wait time 661 LockWaitTimeout int64 662 663 // MetricSchemaStep indicates the step when query metric schemaReplicant. 664 MetricSchemaStep int64 665 // MetricSchemaRangeDuration indicates the step when query metric schemaReplicant. 666 MetricSchemaRangeDuration int64 667 668 // Some data of cluster-level memory blocks will be retrieved many times in different inspection rules, 669 // and the cost of retrieving some data is expensive. We use the `BlockSnapshot` to cache those data 670 // and obtain them lazily, and provide a consistent view of inspection blocks for each inspection rules. 671 // All cached snapshots will be released at the end of retrieving 672 InspectionBlockCache map[string]BlockSnapshot 673 674 // RowCausetEncoder is reused in stochastik for encode event data. 675 RowCausetEncoder rowcodec.CausetEncoder 676 677 // SequenceState cache all sequence's latest value accessed by lastval() builtins. It's a stochastik scoped 678 // variable, and all public methods of SequenceState are currently-safe. 679 SequenceState *SequenceState 680 681 // WindowingUseHighPrecision determines whether to compute window operations without loss of precision. 682 // see https://dev.allegrosql.com/doc/refman/8.0/en/window-function-optimization.html for more details. 683 WindowingUseHighPrecision bool 684 685 // FoundInCausetCache indicates whether this memex was found in plan cache. 686 FoundInCausetCache bool 687 // PrevFoundInCausetCache indicates whether the last memex was found in plan cache. 688 PrevFoundInCausetCache bool 689 690 // OptimizerUseInvisibleIndexes indicates whether optimizer can use invisible index 691 OptimizerUseInvisibleIndexes bool 692 693 // SelectLimit limits the max counts of select memex's output 694 SelectLimit uint64 695 696 // EnableClusteredIndex indicates whether to enable clustered index when creating a new causet. 697 EnableClusteredIndex bool 698 699 // PresumeKeyNotExists indicates lazy existence checking is enabled. 700 PresumeKeyNotExists bool 701 702 // EnableParallelApply indicates that thether to use parallel apply. 703 EnableParallelApply bool 704 705 // ShardAllocateStep indicates the max size of continuous rowid shard in one transaction. 706 ShardAllocateStep int64 707 708 // EnableAmendPessimisticTxn indicates if schemaReplicant change amend is enabled for pessimistic transactions. 709 EnableAmendPessimisticTxn bool 710 711 // LastTxnInfo keeps track the info of last committed transaction. 712 LastTxnInfo ekv.TxnInfo 713 714 // PartitionPruneMode indicates how and when to prune partitions. 715 PartitionPruneMode PartitionPruneMode 716 } 717 718 // UseDynamicPartitionPrune indicates whether use new dynamic partition prune. 719 func (s *StochastikVars) UseDynamicPartitionPrune() bool { 720 return s.PartitionPruneMode == DynamicOnly 721 } 722 723 // PartitionPruneMode presents the prune mode used. 724 type PartitionPruneMode string 725 726 const ( 727 // StaticOnly indicates only prune at plan phase. 728 StaticOnly PartitionPruneMode = "static-only" 729 // DynamicOnly indicates only prune at execute phase. 730 DynamicOnly PartitionPruneMode = "dynamic-only" 731 // StaticButPrepareDynamic indicates prune at plan phase but defCauslect stats need for dynamic prune. 732 StaticButPrepareDynamic PartitionPruneMode = "static-defCauslect-dynamic" 733 ) 734 735 // Valid indicate PruneMode is validated. 736 func (p PartitionPruneMode) Valid() bool { 737 switch p { 738 case StaticOnly, StaticButPrepareDynamic, DynamicOnly: 739 return true 740 default: 741 return false 742 } 743 } 744 745 // PreparedParams contains the parameters of the current prepared memex when executing it. 746 type PreparedParams []types.Causet 747 748 func (pps PreparedParams) String() string { 749 if len(pps) == 0 { 750 return "" 751 } 752 return " [arguments: " + types.CausetsToStrNoErr(pps) + "]" 753 } 754 755 // ConnectionInfo present connection used by audit. 756 type ConnectionInfo struct { 757 ConnectionID uint32 758 ConnectionType string 759 Host string 760 ClientIP string 761 ClientPort string 762 ServerID int 763 ServerPort int 764 Duration float64 765 User string 766 ServerOSLoginUser string 767 OSVersion string 768 ClientVersion string 769 ServerVersion string 770 SSLVersion string 771 PID int 772 EDB string 773 } 774 775 // NewStochastikVars creates a stochastik vars object. 776 func NewStochastikVars() *StochastikVars { 777 vars := &StochastikVars{ 778 Users: make(map[string]types.Causet), 779 systems: make(map[string]string), 780 PreparedStmts: make(map[uint32]interface{}), 781 PreparedStmtNameToID: make(map[string]uint32), 782 PreparedParams: make([]types.Causet, 0, 10), 783 TxnCtx: &TransactionContext{}, 784 RetryInfo: &RetryInfo{}, 785 ActiveRoles: make([]*auth.RoleIdentity, 0, 10), 786 StrictALLEGROSQLMode: true, 787 AutoIncrementIncrement: DefAutoIncrementIncrement, 788 AutoIncrementOffset: DefAutoIncrementOffset, 789 Status: allegrosql.ServerStatusAutocommit, 790 StmtCtx: new(stmtctx.StatementContext), 791 AllowAggPushDown: false, 792 AllowBCJ: false, 793 OptimizerSelectivityLevel: DefMilevaDBOptimizerSelectivityLevel, 794 RetryLimit: DefMilevaDBRetryLimit, 795 DisableTxnAutoRetry: DefMilevaDBDisableTxnAutoRetry, 796 DBSReorgPriority: ekv.PriorityLow, 797 allowInSubqToJoinAnPosetDagg: DefOptInSubqToJoinAnPosetDagg, 798 CorrelationThreshold: DefOptCorrelationThreshold, 799 CorrelationExpFactor: DefOptCorrelationExpFactor, 800 CPUFactor: DefOptCPUFactor, 801 CopCPUFactor: DefOptCopCPUFactor, 802 CopTiFlashConcurrencyFactor: DefOptTiFlashConcurrencyFactor, 803 NetworkFactor: DefOptNetworkFactor, 804 ScanFactor: DefOptScanFactor, 805 DescScanFactor: DefOptDescScanFactor, 806 SeekFactor: DefOptSeekFactor, 807 MemoryFactor: DefOptMemoryFactor, 808 DiskFactor: DefOptDiskFactor, 809 ConcurrencyFactor: DefOptConcurrencyFactor, 810 EnableRadixJoin: false, 811 EnableVectorizedExpression: DefEnableVectorizedExpression, 812 L2CacheSize: cpuid.CPU.Cache.L2, 813 CommandValue: uint32(allegrosql.ComSleep), 814 MilevaDBOptJoinReorderThreshold: DefMilevaDBOptJoinReorderThreshold, 815 SlowQueryFile: config.GetGlobalConfig().Log.SlowQueryFile, 816 WaitSplitRegionFinish: DefMilevaDBWaitSplitRegionFinish, 817 WaitSplitRegionTimeout: DefWaitSplitRegionTimeout, 818 enableIndexMerge: false, 819 EnableNoopFuncs: DefMilevaDBEnableNoopFuncs, 820 replicaRead: ekv.ReplicaReadLeader, 821 AllowRemoveAutoInc: DefMilevaDBAllowRemoveAutoInc, 822 UseCausetBaselines: DefMilevaDBUseCausetBaselines, 823 EvolveCausetBaselines: DefMilevaDBEvolveCausetBaselines, 824 IsolationReadEngines: make(map[ekv.StoreType]struct{}), 825 LockWaitTimeout: DefInnodbLockWaitTimeout * 1000, 826 MetricSchemaStep: DefMilevaDBMetricSchemaStep, 827 MetricSchemaRangeDuration: DefMilevaDBMetricSchemaRangeDuration, 828 SequenceState: NewSequenceState(), 829 WindowingUseHighPrecision: true, 830 PrevFoundInCausetCache: DefMilevaDBFoundInCausetCache, 831 FoundInCausetCache: DefMilevaDBFoundInCausetCache, 832 SelectLimit: math.MaxUint64, 833 AllowAutoRandExplicitInsert: DefMilevaDBAllowAutoRandExplicitInsert, 834 EnableClusteredIndex: DefMilevaDBEnableClusteredIndex, 835 EnableParallelApply: DefMilevaDBEnableParallelApply, 836 ShardAllocateStep: DefMilevaDBShardAllocateStep, 837 EnableChangeDeferredCausetType: DefMilevaDBChangeDeferredCausetType, 838 EnableAmendPessimisticTxn: DefMilevaDBEnableAmendPessimisticTxn, 839 } 840 vars.KVVars = ekv.NewVariables(&vars.Killed) 841 vars.Concurrency = Concurrency{ 842 indexLookupConcurrency: DefIndexLookupConcurrency, 843 indexSerialScanConcurrency: DefIndexSerialScanConcurrency, 844 indexLookupJoinConcurrency: DefIndexLookupJoinConcurrency, 845 hashJoinConcurrency: DefMilevaDBHashJoinConcurrency, 846 projectionConcurrency: DefMilevaDBProjectionConcurrency, 847 distALLEGROSQLScanConcurrency: DefDistALLEGROSQLScanConcurrency, 848 hashAggPartialConcurrency: DefMilevaDBHashAggPartialConcurrency, 849 hashAggFinalConcurrency: DefMilevaDBHashAggFinalConcurrency, 850 windowConcurrency: DefMilevaDBWindowConcurrency, 851 InterlockingDirectorateConcurrency: DefInterlockingDirectorateConcurrency, 852 } 853 vars.MemQuota = MemQuota{ 854 MemQuotaQuery: config.GetGlobalConfig().MemQuotaQuery, 855 NestedLoopJoinCacheCapacity: config.GetGlobalConfig().NestedLoopJoinCacheCapacity, 856 857 // The variables below do not take any effect anymore, it's remaining for compatibility. 858 // TODO: remove them in v4.1 859 MemQuotaHashJoin: DefMilevaDBMemQuotaHashJoin, 860 MemQuotaMergeJoin: DefMilevaDBMemQuotaMergeJoin, 861 MemQuotaSort: DefMilevaDBMemQuotaSort, 862 MemQuotaTopn: DefMilevaDBMemQuotaTopn, 863 MemQuotaIndexLookupReader: DefMilevaDBMemQuotaIndexLookupReader, 864 MemQuotaIndexLookupJoin: DefMilevaDBMemQuotaIndexLookupJoin, 865 MemQuotaNestedLoopApply: DefMilevaDBMemQuotaNestedLoopApply, 866 MemQuotaDistALLEGROSQL: DefMilevaDBMemQuotaDistALLEGROSQL, 867 } 868 vars.BatchSize = BatchSize{ 869 IndexJoinBatchSize: DefIndexJoinBatchSize, 870 IndexLookupSize: DefIndexLookupSize, 871 InitChunkSize: DefInitChunkSize, 872 MaxChunkSize: DefMaxChunkSize, 873 } 874 vars.DMLBatchSize = DefDMLBatchSize 875 var enableStreaming string 876 if config.GetGlobalConfig().EnableStreaming { 877 enableStreaming = "1" 878 } else { 879 enableStreaming = "0" 880 } 881 terror.Log(vars.SetSystemVar(MilevaDBEnableStreaming, enableStreaming)) 882 883 vars.AllowBatchCop = DefMilevaDBAllowBatchCop 884 885 var enableChunkRPC string 886 if config.GetGlobalConfig().EinsteinDBClient.EnableChunkRPC { 887 enableChunkRPC = "1" 888 } else { 889 enableChunkRPC = "0" 890 } 891 terror.Log(vars.SetSystemVar(MilevaDBEnableChunkRPC, enableChunkRPC)) 892 for _, engine := range config.GetGlobalConfig().IsolationRead.Engines { 893 switch engine { 894 case ekv.TiFlash.Name(): 895 vars.IsolationReadEngines[ekv.TiFlash] = struct{}{} 896 case ekv.EinsteinDB.Name(): 897 vars.IsolationReadEngines[ekv.EinsteinDB] = struct{}{} 898 case ekv.MilevaDB.Name(): 899 vars.IsolationReadEngines[ekv.MilevaDB] = struct{}{} 900 } 901 } 902 return vars 903 } 904 905 // GetAllowInSubqToJoinAnPosetDagg get AllowInSubqToJoinAnPosetDagg from allegrosql hints and StochastikVars.allowInSubqToJoinAnPosetDagg. 906 func (s *StochastikVars) GetAllowInSubqToJoinAnPosetDagg() bool { 907 if s.StmtCtx.HasAllowInSubqToJoinAnPosetDaggHint { 908 return s.StmtCtx.AllowInSubqToJoinAnPosetDagg 909 } 910 return s.allowInSubqToJoinAnPosetDagg 911 } 912 913 // SetAllowInSubqToJoinAnPosetDagg set StochastikVars.allowInSubqToJoinAnPosetDagg. 914 func (s *StochastikVars) SetAllowInSubqToJoinAnPosetDagg(val bool) { 915 s.allowInSubqToJoinAnPosetDagg = val 916 } 917 918 // GetEnableCascadesCausetAppend get EnableCascadesCausetAppend from allegrosql hints and StochastikVars.EnableCascadesCausetAppend. 919 func (s *StochastikVars) GetEnableCascadesCausetAppend() bool { 920 if s.StmtCtx.HasEnableCascadesCausetAppendHint { 921 return s.StmtCtx.EnableCascadesCausetAppend 922 } 923 return s.EnableCascadesCausetAppend 924 } 925 926 // SetEnableCascadesCausetAppend set StochastikVars.EnableCascadesCausetAppend. 927 func (s *StochastikVars) SetEnableCascadesCausetAppend(val bool) { 928 s.EnableCascadesCausetAppend = val 929 } 930 931 // GetEnableIndexMerge get EnableIndexMerge from StochastikVars.enableIndexMerge. 932 func (s *StochastikVars) GetEnableIndexMerge() bool { 933 return s.enableIndexMerge 934 } 935 936 // SetEnableIndexMerge set StochastikVars.enableIndexMerge. 937 func (s *StochastikVars) SetEnableIndexMerge(val bool) { 938 s.enableIndexMerge = val 939 } 940 941 // GetReplicaRead get ReplicaRead from allegrosql hints and StochastikVars.replicaRead. 942 func (s *StochastikVars) GetReplicaRead() ekv.ReplicaReadType { 943 if s.StmtCtx.HasReplicaReadHint { 944 return ekv.ReplicaReadType(s.StmtCtx.ReplicaRead) 945 } 946 return s.replicaRead 947 } 948 949 // SetReplicaRead set StochastikVars.replicaRead. 950 func (s *StochastikVars) SetReplicaRead(val ekv.ReplicaReadType) { 951 s.replicaRead = val 952 } 953 954 // GetWriteStmtBufs get pointer of StochastikVars.writeStmtBufs. 955 func (s *StochastikVars) GetWriteStmtBufs() *WriteStmtBufs { 956 return &s.writeStmtBufs 957 } 958 959 // GetSplitRegionTimeout gets split region timeout. 960 func (s *StochastikVars) GetSplitRegionTimeout() time.Duration { 961 return time.Duration(s.WaitSplitRegionTimeout) * time.Second 962 } 963 964 // GetIsolationReadEngines gets isolation read engines. 965 func (s *StochastikVars) GetIsolationReadEngines() map[ekv.StoreType]struct{} { 966 return s.IsolationReadEngines 967 } 968 969 // CleanBuffers cleans the temporary bufs 970 func (s *StochastikVars) CleanBuffers() { 971 s.GetWriteStmtBufs().clean() 972 } 973 974 // AllocCausetDeferredCausetID allocates defCausumn id for plan. 975 func (s *StochastikVars) AllocCausetDeferredCausetID() int64 { 976 s.CausetDeferredCausetID++ 977 return s.CausetDeferredCausetID 978 } 979 980 // GetCharsetInfo gets charset and defCauslation for current context. 981 // What character set should the server translate a memex to after receiving it? 982 // For this, the server uses the character_set_connection and defCauslation_connection system variables. 983 // It converts memexs sent by the client from character_set_client to character_set_connection 984 // (except for string literals that have an introducer such as _latin1 or _utf8). 985 // defCauslation_connection is important for comparisons of literal strings. 986 // For comparisons of strings with defCausumn values, defCauslation_connection does not matter because defCausumns 987 // have their own defCauslation, which has a higher defCauslation precedence. 988 // See https://dev.allegrosql.com/doc/refman/5.7/en/charset-connection.html 989 func (s *StochastikVars) GetCharsetInfo() (charset, defCauslation string) { 990 charset = s.systems[CharacterSetConnection] 991 defCauslation = s.systems[DefCauslationConnection] 992 return 993 } 994 995 // SetUserVar set the value and defCauslation for user defined variable. 996 func (s *StochastikVars) SetUserVar(varName string, svalue string, defCauslation string) { 997 if len(defCauslation) > 0 { 998 s.Users[varName] = types.NewDefCauslationStringCauset(stringutil.Copy(svalue), defCauslation, defCauslate.DefaultLen) 999 } else { 1000 _, defCauslation = s.GetCharsetInfo() 1001 s.Users[varName] = types.NewDefCauslationStringCauset(stringutil.Copy(svalue), defCauslation, defCauslate.DefaultLen) 1002 } 1003 } 1004 1005 // SetLastInsertID saves the last insert id to the stochastik context. 1006 // TODO: we may causetstore the result for last_insert_id sys var later. 1007 func (s *StochastikVars) SetLastInsertID(insertID uint64) { 1008 s.StmtCtx.LastInsertID = insertID 1009 } 1010 1011 // SetStatusFlag sets the stochastik server status variable. 1012 // If on is ture sets the flag in stochastik status, 1013 // otherwise removes the flag. 1014 func (s *StochastikVars) SetStatusFlag(flag uint16, on bool) { 1015 if on { 1016 s.Status |= flag 1017 return 1018 } 1019 s.Status &= ^flag 1020 } 1021 1022 // GetStatusFlag gets the stochastik server status variable, returns true if it is on. 1023 func (s *StochastikVars) GetStatusFlag(flag uint16) bool { 1024 return s.Status&flag > 0 1025 } 1026 1027 // InTxn returns if the stochastik is in transaction. 1028 func (s *StochastikVars) InTxn() bool { 1029 return s.GetStatusFlag(allegrosql.ServerStatusInTrans) 1030 } 1031 1032 // IsAutocommit returns if the stochastik is set to autocommit. 1033 func (s *StochastikVars) IsAutocommit() bool { 1034 return s.GetStatusFlag(allegrosql.ServerStatusAutocommit) 1035 } 1036 1037 // IsReadConsistencyTxn if true it means the transaction is an read consistency (read committed) transaction. 1038 func (s *StochastikVars) IsReadConsistencyTxn() bool { 1039 if s.TxnCtx.Isolation != "" { 1040 return s.TxnCtx.Isolation == ast.ReadCommitted 1041 } 1042 if s.txnIsolationLevelOneShot.state == oneShotUse { 1043 s.TxnCtx.Isolation = s.txnIsolationLevelOneShot.value 1044 } 1045 if s.TxnCtx.Isolation == "" { 1046 s.TxnCtx.Isolation, _ = s.GetSystemVar(TxnIsolation) 1047 } 1048 return s.TxnCtx.Isolation == ast.ReadCommitted 1049 } 1050 1051 // SetTxnIsolationLevelOneShotStateForNextTxn sets the txnIsolationLevelOneShot.state for next transaction. 1052 func (s *StochastikVars) SetTxnIsolationLevelOneShotStateForNextTxn() { 1053 if isoLevelOneShot := &s.txnIsolationLevelOneShot; isoLevelOneShot.state != oneShotDef { 1054 switch isoLevelOneShot.state { 1055 case oneShotSet: 1056 isoLevelOneShot.state = oneShotUse 1057 case oneShotUse: 1058 isoLevelOneShot.state = oneShotDef 1059 isoLevelOneShot.value = "" 1060 } 1061 } 1062 } 1063 1064 // IsPessimisticReadConsistency if true it means the memex is in an read consistency pessimistic transaction. 1065 func (s *StochastikVars) IsPessimisticReadConsistency() bool { 1066 return s.TxnCtx.IsPessimistic && s.IsReadConsistencyTxn() 1067 } 1068 1069 // GetNextPreparedStmtID generates and returns the next stochastik scope prepared memex id. 1070 func (s *StochastikVars) GetNextPreparedStmtID() uint32 { 1071 s.preparedStmtID++ 1072 return s.preparedStmtID 1073 } 1074 1075 // Location returns the value of time_zone stochastik variable. If it is nil, then return time.Local. 1076 func (s *StochastikVars) Location() *time.Location { 1077 loc := s.TimeZone 1078 if loc == nil { 1079 loc = timeutil.SystemLocation() 1080 } 1081 return loc 1082 } 1083 1084 // GetSystemVar gets the string value of a system variable. 1085 func (s *StochastikVars) GetSystemVar(name string) (string, bool) { 1086 if name == WarningCount { 1087 return strconv.Itoa(s.SysWarningCount), true 1088 } else if name == ErrorCount { 1089 return strconv.Itoa(int(s.SysErrorCount)), true 1090 } 1091 val, ok := s.systems[name] 1092 return val, ok 1093 } 1094 1095 func (s *StochastikVars) setDBSReorgPriority(val string) { 1096 val = strings.ToLower(val) 1097 switch val { 1098 case "priority_low": 1099 s.DBSReorgPriority = ekv.PriorityLow 1100 case "priority_normal": 1101 s.DBSReorgPriority = ekv.PriorityNormal 1102 case "priority_high": 1103 s.DBSReorgPriority = ekv.PriorityHigh 1104 default: 1105 s.DBSReorgPriority = ekv.PriorityLow 1106 } 1107 } 1108 1109 // AddPreparedStmt adds prepareStmt to current stochastik and count in global. 1110 func (s *StochastikVars) AddPreparedStmt(stmtID uint32, stmt interface{}) error { 1111 if _, exists := s.PreparedStmts[stmtID]; !exists { 1112 valStr, _ := s.GetSystemVar(MaxPreparedStmtCount) 1113 maxPreparedStmtCount, err := strconv.ParseInt(valStr, 10, 64) 1114 if err != nil { 1115 maxPreparedStmtCount = DefMaxPreparedStmtCount 1116 } 1117 newPreparedStmtCount := atomic.AddInt64(&preparedStmtCount, 1) 1118 if maxPreparedStmtCount >= 0 && newPreparedStmtCount > maxPreparedStmtCount { 1119 atomic.AddInt64(&preparedStmtCount, -1) 1120 return ErrMaxPreparedStmtCountReached.GenWithStackByArgs(maxPreparedStmtCount) 1121 } 1122 metrics.PreparedStmtGauge.Set(float64(newPreparedStmtCount)) 1123 } 1124 s.PreparedStmts[stmtID] = stmt 1125 return nil 1126 } 1127 1128 // RemovePreparedStmt removes preparedStmt from current stochastik and decrease count in global. 1129 func (s *StochastikVars) RemovePreparedStmt(stmtID uint32) { 1130 _, exists := s.PreparedStmts[stmtID] 1131 if !exists { 1132 return 1133 } 1134 delete(s.PreparedStmts, stmtID) 1135 afterMinus := atomic.AddInt64(&preparedStmtCount, -1) 1136 metrics.PreparedStmtGauge.Set(float64(afterMinus)) 1137 } 1138 1139 // WithdrawAllPreparedStmt remove all preparedStmt in current stochastik and decrease count in global. 1140 func (s *StochastikVars) WithdrawAllPreparedStmt() { 1141 psCount := len(s.PreparedStmts) 1142 if psCount == 0 { 1143 return 1144 } 1145 afterMinus := atomic.AddInt64(&preparedStmtCount, -int64(psCount)) 1146 metrics.PreparedStmtGauge.Set(float64(afterMinus)) 1147 } 1148 1149 // SetSystemVar sets the value of a system variable. 1150 func (s *StochastikVars) SetSystemVar(name string, val string) error { 1151 switch name { 1152 case TxnIsolationOneShot: 1153 switch val { 1154 case "SERIALIZABLE", "READ-UNCOMMITTED": 1155 skipIsolationLevelCheck, err := GetStochastikSystemVar(s, MilevaDBSkipIsolationLevelCheck) 1156 returnErr := ErrUnsupportedIsolationLevel.GenWithStackByArgs(val) 1157 if err != nil { 1158 returnErr = err 1159 } 1160 if !MilevaDBOptOn(skipIsolationLevelCheck) || err != nil { 1161 return returnErr 1162 } 1163 //SET TRANSACTION ISOLATION LEVEL will affect two internal variables: 1164 // 1. tx_isolation 1165 // 2. transaction_isolation 1166 // The following if condition is used to deduplicate two same warnings. 1167 if name == "transaction_isolation" { 1168 s.StmtCtx.AppendWarning(returnErr) 1169 } 1170 } 1171 s.txnIsolationLevelOneShot.state = oneShotSet 1172 s.txnIsolationLevelOneShot.value = val 1173 case TimeZone: 1174 tz, err := parseTimeZone(val) 1175 if err != nil { 1176 return err 1177 } 1178 s.TimeZone = tz 1179 case ALLEGROSQLModeVar: 1180 val = allegrosql.FormatALLEGROSQLModeStr(val) 1181 // Modes is a list of different modes separated by commas. 1182 sqlMode, err2 := allegrosql.GetALLEGROSQLMode(val) 1183 if err2 != nil { 1184 return errors.Trace(err2) 1185 } 1186 s.StrictALLEGROSQLMode = sqlMode.HasStrictMode() 1187 s.ALLEGROSQLMode = sqlMode 1188 s.SetStatusFlag(allegrosql.ServerStatusNoBackslashEscaped, sqlMode.HasNoBackslashEscapesMode()) 1189 case MilevaDBSnapshot: 1190 err := setSnapshotTS(s, val) 1191 if err != nil { 1192 return err 1193 } 1194 case AutoCommit: 1195 isAutocommit := MilevaDBOptOn(val) 1196 s.SetStatusFlag(allegrosql.ServerStatusAutocommit, isAutocommit) 1197 if isAutocommit { 1198 s.SetStatusFlag(allegrosql.ServerStatusInTrans, false) 1199 } 1200 case AutoIncrementIncrement: 1201 // AutoIncrementIncrement is valid in [1, 65535]. 1202 s.AutoIncrementIncrement = milevadbOptPositiveInt32(val, DefAutoIncrementIncrement) 1203 case AutoIncrementOffset: 1204 // AutoIncrementOffset is valid in [1, 65535]. 1205 s.AutoIncrementOffset = milevadbOptPositiveInt32(val, DefAutoIncrementOffset) 1206 case MaxInterDircutionTime: 1207 timeoutMS := milevadbOptPositiveInt32(val, 0) 1208 s.MaxInterDircutionTime = uint64(timeoutMS) 1209 case InnodbLockWaitTimeout: 1210 lockWaitSec := milevadbOptInt64(val, DefInnodbLockWaitTimeout) 1211 s.LockWaitTimeout = lockWaitSec * 1000 1212 case WindowingUseHighPrecision: 1213 s.WindowingUseHighPrecision = MilevaDBOptOn(val) 1214 case MilevaDBSkipUTF8Check: 1215 s.SkipUTF8Check = MilevaDBOptOn(val) 1216 case MilevaDBSkipASCIICheck: 1217 s.SkipASCIICheck = MilevaDBOptOn(val) 1218 case MilevaDBOptAggPushDown: 1219 s.AllowAggPushDown = MilevaDBOptOn(val) 1220 case MilevaDBOptBCJ: 1221 s.AllowBCJ = MilevaDBOptOn(val) 1222 case MilevaDBOptDistinctAggPushDown: 1223 s.AllowDistinctAggPushDown = MilevaDBOptOn(val) 1224 case MilevaDBOptWriteRowID: 1225 s.AllowWriteRowID = MilevaDBOptOn(val) 1226 case MilevaDBOptInSubqToJoinAnPosetDagg: 1227 s.SetAllowInSubqToJoinAnPosetDagg(MilevaDBOptOn(val)) 1228 case MilevaDBOptCorrelationThreshold: 1229 s.CorrelationThreshold = milevadbOptFloat64(val, DefOptCorrelationThreshold) 1230 case MilevaDBOptCorrelationExpFactor: 1231 s.CorrelationExpFactor = int(milevadbOptInt64(val, DefOptCorrelationExpFactor)) 1232 case MilevaDBOptCPUFactor: 1233 s.CPUFactor = milevadbOptFloat64(val, DefOptCPUFactor) 1234 case MilevaDBOptCopCPUFactor: 1235 s.CopCPUFactor = milevadbOptFloat64(val, DefOptCopCPUFactor) 1236 case MilevaDBOptTiFlashConcurrencyFactor: 1237 s.CopTiFlashConcurrencyFactor = milevadbOptFloat64(val, DefOptTiFlashConcurrencyFactor) 1238 case MilevaDBOptNetworkFactor: 1239 s.NetworkFactor = milevadbOptFloat64(val, DefOptNetworkFactor) 1240 case MilevaDBOptScanFactor: 1241 s.ScanFactor = milevadbOptFloat64(val, DefOptScanFactor) 1242 case MilevaDBOptDescScanFactor: 1243 s.DescScanFactor = milevadbOptFloat64(val, DefOptDescScanFactor) 1244 case MilevaDBOptSeekFactor: 1245 s.SeekFactor = milevadbOptFloat64(val, DefOptSeekFactor) 1246 case MilevaDBOptMemoryFactor: 1247 s.MemoryFactor = milevadbOptFloat64(val, DefOptMemoryFactor) 1248 case MilevaDBOptDiskFactor: 1249 s.DiskFactor = milevadbOptFloat64(val, DefOptDiskFactor) 1250 case MilevaDBOptConcurrencyFactor: 1251 s.ConcurrencyFactor = milevadbOptFloat64(val, DefOptConcurrencyFactor) 1252 case MilevaDBIndexLookupConcurrency: 1253 s.indexLookupConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1254 case MilevaDBIndexLookupJoinConcurrency: 1255 s.indexLookupJoinConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1256 case MilevaDBIndexJoinBatchSize: 1257 s.IndexJoinBatchSize = milevadbOptPositiveInt32(val, DefIndexJoinBatchSize) 1258 case MilevaDBAllowBatchCop: 1259 s.AllowBatchCop = int(milevadbOptInt64(val, DefMilevaDBAllowBatchCop)) 1260 case MilevaDBIndexLookupSize: 1261 s.IndexLookupSize = milevadbOptPositiveInt32(val, DefIndexLookupSize) 1262 case MilevaDBHashJoinConcurrency: 1263 s.hashJoinConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1264 case MilevaDBProjectionConcurrency: 1265 s.projectionConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1266 case MilevaDBHashAggPartialConcurrency: 1267 s.hashAggPartialConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1268 case MilevaDBHashAggFinalConcurrency: 1269 s.hashAggFinalConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1270 case MilevaDBWindowConcurrency: 1271 s.windowConcurrency = milevadbOptPositiveInt32(val, ConcurrencyUnset) 1272 case MilevaDBDistALLEGROSQLScanConcurrency: 1273 s.distALLEGROSQLScanConcurrency = milevadbOptPositiveInt32(val, DefDistALLEGROSQLScanConcurrency) 1274 case MilevaDBIndexSerialScanConcurrency: 1275 s.indexSerialScanConcurrency = milevadbOptPositiveInt32(val, DefIndexSerialScanConcurrency) 1276 case MilevaDBInterlockingDirectorateConcurrency: 1277 s.InterlockingDirectorateConcurrency = milevadbOptPositiveInt32(val, DefInterlockingDirectorateConcurrency) 1278 case MilevaDBBackoffLockFast: 1279 s.KVVars.BackoffLockFast = milevadbOptPositiveInt32(val, ekv.DefBackoffLockFast) 1280 case MilevaDBBackOffWeight: 1281 s.KVVars.BackOffWeight = milevadbOptPositiveInt32(val, ekv.DefBackOffWeight) 1282 case MilevaDBConstraintCheckInPlace: 1283 s.ConstraintCheckInPlace = MilevaDBOptOn(val) 1284 case MilevaDBBatchInsert: 1285 s.BatchInsert = MilevaDBOptOn(val) 1286 case MilevaDBBatchDelete: 1287 s.BatchDelete = MilevaDBOptOn(val) 1288 case MilevaDBBatchCommit: 1289 s.BatchCommit = MilevaDBOptOn(val) 1290 case MilevaDBDMLBatchSize: 1291 s.DMLBatchSize = int(milevadbOptInt64(val, DefOptCorrelationExpFactor)) 1292 case MilevaDBCurrentTS, MilevaDBLastTxnInfo, MilevaDBConfig: 1293 return ErrReadOnly 1294 case MilevaDBMaxChunkSize: 1295 s.MaxChunkSize = milevadbOptPositiveInt32(val, DefMaxChunkSize) 1296 case MilevaDBInitChunkSize: 1297 s.InitChunkSize = milevadbOptPositiveInt32(val, DefInitChunkSize) 1298 case MilevaDBMemQuotaQuery: 1299 s.MemQuotaQuery = milevadbOptInt64(val, config.GetGlobalConfig().MemQuotaQuery) 1300 case MilevaDBNestedLoopJoinCacheCapacity: 1301 s.NestedLoopJoinCacheCapacity = milevadbOptInt64(val, config.GetGlobalConfig().NestedLoopJoinCacheCapacity) 1302 case MilevaDBMemQuotaHashJoin: 1303 s.MemQuotaHashJoin = milevadbOptInt64(val, DefMilevaDBMemQuotaHashJoin) 1304 case MilevaDBMemQuotaMergeJoin: 1305 s.MemQuotaMergeJoin = milevadbOptInt64(val, DefMilevaDBMemQuotaMergeJoin) 1306 case MilevaDBMemQuotaSort: 1307 s.MemQuotaSort = milevadbOptInt64(val, DefMilevaDBMemQuotaSort) 1308 case MilevaDBMemQuotaTopn: 1309 s.MemQuotaTopn = milevadbOptInt64(val, DefMilevaDBMemQuotaTopn) 1310 case MilevaDBMemQuotaIndexLookupReader: 1311 s.MemQuotaIndexLookupReader = milevadbOptInt64(val, DefMilevaDBMemQuotaIndexLookupReader) 1312 case MilevaDBMemQuotaIndexLookupJoin: 1313 s.MemQuotaIndexLookupJoin = milevadbOptInt64(val, DefMilevaDBMemQuotaIndexLookupJoin) 1314 case MilevaDBMemQuotaNestedLoopApply: 1315 s.MemQuotaNestedLoopApply = milevadbOptInt64(val, DefMilevaDBMemQuotaNestedLoopApply) 1316 case MilevaDBGeneralLog: 1317 atomic.StoreUint32(&ProcessGeneralLog, uint32(milevadbOptPositiveInt32(val, DefMilevaDBGeneralLog))) 1318 case MilevaDBPProfALLEGROSQLCPU: 1319 EnablePProfALLEGROSQLCPU.CausetStore(uint32(milevadbOptPositiveInt32(val, DefMilevaDBPProfALLEGROSQLCPU)) > 0) 1320 case MilevaDBDBSSlowOprThreshold: 1321 atomic.StoreUint32(&DBSSlowOprThreshold, uint32(milevadbOptPositiveInt32(val, DefMilevaDBDBSSlowOprThreshold))) 1322 case MilevaDBRetryLimit: 1323 s.RetryLimit = milevadbOptInt64(val, DefMilevaDBRetryLimit) 1324 case MilevaDBDisableTxnAutoRetry: 1325 s.DisableTxnAutoRetry = MilevaDBOptOn(val) 1326 case MilevaDBEnableStreaming: 1327 s.EnableStreaming = MilevaDBOptOn(val) 1328 case MilevaDBEnableChunkRPC: 1329 s.EnableChunkRPC = MilevaDBOptOn(val) 1330 case MilevaDBEnableCascadesCausetAppend: 1331 s.SetEnableCascadesCausetAppend(MilevaDBOptOn(val)) 1332 case MilevaDBOptimizerSelectivityLevel: 1333 s.OptimizerSelectivityLevel = milevadbOptPositiveInt32(val, DefMilevaDBOptimizerSelectivityLevel) 1334 case MilevaDBEnableBlockPartition: 1335 s.EnableBlockPartition = val 1336 case MilevaDBDBSReorgPriority: 1337 s.setDBSReorgPriority(val) 1338 case MilevaDBForcePriority: 1339 atomic.StoreInt32(&ForcePriority, int32(allegrosql.Str2Priority(val))) 1340 case MilevaDBEnableRadixJoin: 1341 s.EnableRadixJoin = MilevaDBOptOn(val) 1342 case MilevaDBEnableWindowFunction: 1343 s.EnableWindowFunction = MilevaDBOptOn(val) 1344 case MilevaDBEnableVectorizedExpression: 1345 s.EnableVectorizedExpression = MilevaDBOptOn(val) 1346 case MilevaDBOptJoinReorderThreshold: 1347 s.MilevaDBOptJoinReorderThreshold = milevadbOptPositiveInt32(val, DefMilevaDBOptJoinReorderThreshold) 1348 case MilevaDBSlowQueryFile: 1349 s.SlowQueryFile = val 1350 case MilevaDBEnableFastAnalyze: 1351 s.EnableFastAnalyze = MilevaDBOptOn(val) 1352 case MilevaDBWaitSplitRegionFinish: 1353 s.WaitSplitRegionFinish = MilevaDBOptOn(val) 1354 case MilevaDBWaitSplitRegionTimeout: 1355 s.WaitSplitRegionTimeout = uint64(milevadbOptPositiveInt32(val, DefWaitSplitRegionTimeout)) 1356 case MilevaDBExpensiveQueryTimeThreshold: 1357 atomic.StoreUint64(&ExpensiveQueryTimeThreshold, uint64(milevadbOptPositiveInt32(val, DefMilevaDBExpensiveQueryTimeThreshold))) 1358 case MilevaDBTxnMode: 1359 s.TxnMode = strings.ToUpper(val) 1360 case MilevaDBRowFormatVersion: 1361 formatVersion := int(milevadbOptInt64(val, DefMilevaDBRowFormatV1)) 1362 if formatVersion == DefMilevaDBRowFormatV1 { 1363 s.RowCausetEncoder.Enable = false 1364 } else if formatVersion == DefMilevaDBRowFormatV2 { 1365 s.RowCausetEncoder.Enable = true 1366 } 1367 case MilevaDBLowResolutionTSO: 1368 s.LowResolutionTSO = MilevaDBOptOn(val) 1369 case MilevaDBEnableIndexMerge: 1370 s.SetEnableIndexMerge(MilevaDBOptOn(val)) 1371 case MilevaDBEnableNoopFuncs: 1372 s.EnableNoopFuncs = MilevaDBOptOn(val) 1373 case MilevaDBReplicaRead: 1374 if strings.EqualFold(val, "follower") { 1375 s.SetReplicaRead(ekv.ReplicaReadFollower) 1376 } else if strings.EqualFold(val, "leader-and-follower") { 1377 s.SetReplicaRead(ekv.ReplicaReadMixed) 1378 } else if strings.EqualFold(val, "leader") || len(val) == 0 { 1379 s.SetReplicaRead(ekv.ReplicaReadLeader) 1380 } 1381 case MilevaDBAllowRemoveAutoInc: 1382 s.AllowRemoveAutoInc = MilevaDBOptOn(val) 1383 // It's a global variable, but it also wants to be cached in server. 1384 case MilevaDBMaxDeltaSchemaCount: 1385 SetMaxDeltaSchemaCount(milevadbOptInt64(val, DefMilevaDBMaxDeltaSchemaCount)) 1386 case MilevaDBUseCausetBaselines: 1387 s.UseCausetBaselines = MilevaDBOptOn(val) 1388 case MilevaDBEvolveCausetBaselines: 1389 s.EvolveCausetBaselines = MilevaDBOptOn(val) 1390 case MilevaDBIsolationReadEngines: 1391 s.IsolationReadEngines = make(map[ekv.StoreType]struct{}) 1392 for _, engine := range strings.Split(val, ",") { 1393 switch engine { 1394 case ekv.EinsteinDB.Name(): 1395 s.IsolationReadEngines[ekv.EinsteinDB] = struct{}{} 1396 case ekv.TiFlash.Name(): 1397 s.IsolationReadEngines[ekv.TiFlash] = struct{}{} 1398 case ekv.MilevaDB.Name(): 1399 s.IsolationReadEngines[ekv.MilevaDB] = struct{}{} 1400 } 1401 } 1402 case MilevaDBStoreLimit: 1403 storeutil.StoreLimit.CausetStore(milevadbOptInt64(val, DefMilevaDBStoreLimit)) 1404 case MilevaDBMetricSchemaStep: 1405 s.MetricSchemaStep = milevadbOptInt64(val, DefMilevaDBMetricSchemaStep) 1406 case MilevaDBMetricSchemaRangeDuration: 1407 s.MetricSchemaRangeDuration = milevadbOptInt64(val, DefMilevaDBMetricSchemaRangeDuration) 1408 case DefCauslationConnection, DefCauslationDatabase, DefCauslationServer: 1409 if _, err := defCauslate.GetDefCauslationByName(val); err != nil { 1410 var ok bool 1411 var charsetVal string 1412 var err2 error 1413 if name == DefCauslationConnection { 1414 charsetVal, ok = s.systems[CharacterSetConnection] 1415 } else if name == DefCauslationDatabase { 1416 charsetVal, ok = s.systems[CharsetDatabase] 1417 } else { 1418 // DefCauslationServer 1419 charsetVal, ok = s.systems[CharacterSetServer] 1420 } 1421 if !ok { 1422 return err 1423 } 1424 val, err2 = charset.GetDefaultDefCauslation(charsetVal) 1425 if err2 != nil { 1426 return err2 1427 } 1428 logutil.BgLogger().Warn(err.Error()) 1429 } 1430 case MilevaDBSlowLogThreshold: 1431 atomic.StoreUint64(&config.GetGlobalConfig().Log.SlowThreshold, uint64(milevadbOptInt64(val, logutil.DefaultSlowThreshold))) 1432 case MilevaDBRecordCausetInSlowLog: 1433 atomic.StoreUint32(&config.GetGlobalConfig().Log.RecordCausetInSlowLog, uint32(milevadbOptInt64(val, logutil.DefaultRecordCausetInSlowLog))) 1434 case MilevaDBEnableSlowLog: 1435 config.GetGlobalConfig().Log.EnableSlowLog = MilevaDBOptOn(val) 1436 case MilevaDBQueryLogMaxLen: 1437 atomic.StoreUint64(&config.GetGlobalConfig().Log.QueryLogMaxLen, uint64(milevadbOptInt64(val, logutil.DefaultQueryLogMaxLen))) 1438 case MilevaDBCheckMb4ValueInUTF8: 1439 config.GetGlobalConfig().CheckMb4ValueInUTF8 = MilevaDBOptOn(val) 1440 case MilevaDBFoundInCausetCache: 1441 s.FoundInCausetCache = MilevaDBOptOn(val) 1442 case MilevaDBEnableDefCauslectInterDircutionInfo: 1443 config.GetGlobalConfig().EnableDefCauslectInterDircutionInfo = MilevaDBOptOn(val) 1444 case ALLEGROSQLSelectLimit: 1445 result, err := strconv.ParseUint(val, 10, 64) 1446 if err != nil { 1447 return errors.Trace(err) 1448 } 1449 s.SelectLimit = result 1450 case MilevaDBAllowAutoRandExplicitInsert: 1451 s.AllowAutoRandExplicitInsert = MilevaDBOptOn(val) 1452 case MilevaDBEnableClusteredIndex: 1453 s.EnableClusteredIndex = MilevaDBOptOn(val) 1454 case MilevaDBPartitionPruneMode: 1455 s.PartitionPruneMode = PartitionPruneMode(strings.ToLower(strings.TrimSpace(val))) 1456 case MilevaDBEnableParallelApply: 1457 s.EnableParallelApply = MilevaDBOptOn(val) 1458 case MilevaDBSlowLogMasking, MilevaDBRedactLog: 1459 config.SetRedactLog(MilevaDBOptOn(val)) 1460 case MilevaDBShardAllocateStep: 1461 s.ShardAllocateStep = milevadbOptInt64(val, DefMilevaDBShardAllocateStep) 1462 case MilevaDBEnableChangeDeferredCausetType: 1463 s.EnableChangeDeferredCausetType = MilevaDBOptOn(val) 1464 case MilevaDBEnableAmendPessimisticTxn: 1465 s.EnableAmendPessimisticTxn = MilevaDBOptOn(val) 1466 } 1467 s.systems[name] = val 1468 return nil 1469 } 1470 1471 // GetReadableTxnMode returns the stochastik variable TxnMode but rewrites it to "OPTIMISTIC" when it's empty. 1472 func (s *StochastikVars) GetReadableTxnMode() string { 1473 txnMode := s.TxnMode 1474 if txnMode == "" { 1475 txnMode = ast.Optimistic 1476 } 1477 return txnMode 1478 } 1479 1480 func (s *StochastikVars) setTxnMode(val string) error { 1481 switch strings.ToUpper(val) { 1482 case ast.Pessimistic: 1483 s.TxnMode = ast.Pessimistic 1484 case ast.Optimistic: 1485 s.TxnMode = ast.Optimistic 1486 case "": 1487 s.TxnMode = "" 1488 default: 1489 return ErrWrongValueForVar.FastGenByArgs(MilevaDBTxnMode, val) 1490 } 1491 return nil 1492 } 1493 1494 // SetPrevStmtDigest sets the digest of the previous memex. 1495 func (s *StochastikVars) SetPrevStmtDigest(prevStmtDigest string) { 1496 s.prevStmtDigest = prevStmtDigest 1497 } 1498 1499 // GetPrevStmtDigest returns the digest of the previous memex. 1500 func (s *StochastikVars) GetPrevStmtDigest() string { 1501 // Because `prevStmt` may be truncated, so it's senseless to normalize it. 1502 // Even if `prevStmtDigest` is empty but `prevStmt` is not, just return it anyway. 1503 return s.prevStmtDigest 1504 } 1505 1506 // LazyCheckKeyNotExists returns if we can lazy check key not exists. 1507 func (s *StochastikVars) LazyCheckKeyNotExists() bool { 1508 return s.PresumeKeyNotExists || (s.TxnCtx.IsPessimistic && !s.StmtCtx.DupKeyAsWarning) 1509 } 1510 1511 // SetLocalSystemVar sets values of the local variables which in "server" scope. 1512 func SetLocalSystemVar(name string, val string) { 1513 switch name { 1514 case MilevaDBDBSReorgWorkerCount: 1515 SetDBSReorgWorkerCounter(int32(milevadbOptPositiveInt32(val, DefMilevaDBDBSReorgWorkerCount))) 1516 case MilevaDBDBSReorgBatchSize: 1517 SetDBSReorgBatchSize(int32(milevadbOptPositiveInt32(val, DefMilevaDBDBSReorgBatchSize))) 1518 case MilevaDBDBSErrorCountLimit: 1519 SetDBSErrorCountLimit(milevadbOptInt64(val, DefMilevaDBDBSErrorCountLimit)) 1520 } 1521 } 1522 1523 // special stochastik variables. 1524 const ( 1525 ALLEGROSQLModeVar = "sql_mode" 1526 CharacterSetResults = "character_set_results" 1527 MaxAllowedPacket = "max_allowed_packet" 1528 TimeZone = "time_zone" 1529 TxnIsolation = "tx_isolation" 1530 TransactionIsolation = "transaction_isolation" 1531 TxnIsolationOneShot = "tx_isolation_one_shot" 1532 MaxInterDircutionTime = "max_execution_time" 1533 ) 1534 1535 // these variables are useless for MilevaDB, but still need to validate their values for some compatible issues. 1536 // TODO: some more variables need to be added here. 1537 const ( 1538 serverReadOnly = "read_only" 1539 ) 1540 1541 var ( 1542 // TxIsolationNames are the valid values of the variable "tx_isolation" or "transaction_isolation". 1543 TxIsolationNames = map[string]struct{}{ 1544 "READ-UNCOMMITTED": {}, 1545 "READ-COMMITTED": {}, 1546 "REPEATABLE-READ": {}, 1547 "SERIALIZABLE": {}, 1548 } 1549 ) 1550 1551 // BlockDelta stands for the changed count for one causet or partition. 1552 type BlockDelta struct { 1553 Delta int64 1554 Count int64 1555 DefCausSize map[int64]int64 1556 InitTime time.Time // InitTime is the time that this delta is generated. 1557 } 1558 1559 // ConcurrencyUnset means the value the of the concurrency related variable is unset. 1560 const ConcurrencyUnset = -1 1561 1562 // Concurrency defines concurrency values. 1563 type Concurrency struct { 1564 // indexLookupConcurrency is the number of concurrent index lookup worker. 1565 // indexLookupConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1566 indexLookupConcurrency int 1567 1568 // indexLookupJoinConcurrency is the number of concurrent index lookup join inner worker. 1569 // indexLookupJoinConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1570 indexLookupJoinConcurrency int 1571 1572 // distALLEGROSQLScanConcurrency is the number of concurrent dist ALLEGROALLEGROSQL scan worker. 1573 // distALLEGROSQLScanConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1574 distALLEGROSQLScanConcurrency int 1575 1576 // hashJoinConcurrency is the number of concurrent hash join outer worker. 1577 // hashJoinConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1578 hashJoinConcurrency int 1579 1580 // projectionConcurrency is the number of concurrent projection worker. 1581 // projectionConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1582 projectionConcurrency int 1583 1584 // hashAggPartialConcurrency is the number of concurrent hash aggregation partial worker. 1585 // hashAggPartialConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1586 hashAggPartialConcurrency int 1587 1588 // hashAggFinalConcurrency is the number of concurrent hash aggregation final worker. 1589 // hashAggFinalConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1590 hashAggFinalConcurrency int 1591 1592 // windowConcurrency is the number of concurrent window worker. 1593 // windowConcurrency is deprecated, use InterlockingDirectorateConcurrency instead. 1594 windowConcurrency int 1595 1596 // indexSerialScanConcurrency is the number of concurrent index serial scan worker. 1597 indexSerialScanConcurrency int 1598 1599 // InterlockingDirectorateConcurrency is the number of concurrent worker for all interlocks. 1600 InterlockingDirectorateConcurrency int 1601 } 1602 1603 // SetIndexLookupConcurrency set the number of concurrent index lookup worker. 1604 func (c *Concurrency) SetIndexLookupConcurrency(n int) { 1605 c.indexLookupConcurrency = n 1606 } 1607 1608 // SetIndexLookupJoinConcurrency set the number of concurrent index lookup join inner worker. 1609 func (c *Concurrency) SetIndexLookupJoinConcurrency(n int) { 1610 c.indexLookupJoinConcurrency = n 1611 } 1612 1613 // SetDistALLEGROSQLScanConcurrency set the number of concurrent dist ALLEGROALLEGROSQL scan worker. 1614 func (c *Concurrency) SetDistALLEGROSQLScanConcurrency(n int) { 1615 c.distALLEGROSQLScanConcurrency = n 1616 } 1617 1618 // SetHashJoinConcurrency set the number of concurrent hash join outer worker. 1619 func (c *Concurrency) SetHashJoinConcurrency(n int) { 1620 c.hashJoinConcurrency = n 1621 } 1622 1623 // SetProjectionConcurrency set the number of concurrent projection worker. 1624 func (c *Concurrency) SetProjectionConcurrency(n int) { 1625 c.projectionConcurrency = n 1626 } 1627 1628 // SetHashAggPartialConcurrency set the number of concurrent hash aggregation partial worker. 1629 func (c *Concurrency) SetHashAggPartialConcurrency(n int) { 1630 c.hashAggPartialConcurrency = n 1631 } 1632 1633 // SetHashAggFinalConcurrency set the number of concurrent hash aggregation final worker. 1634 func (c *Concurrency) SetHashAggFinalConcurrency(n int) { 1635 c.hashAggFinalConcurrency = n 1636 } 1637 1638 // SetWindowConcurrency set the number of concurrent window worker. 1639 func (c *Concurrency) SetWindowConcurrency(n int) { 1640 c.windowConcurrency = n 1641 } 1642 1643 // SetIndexSerialScanConcurrency set the number of concurrent index serial scan worker. 1644 func (c *Concurrency) SetIndexSerialScanConcurrency(n int) { 1645 c.indexSerialScanConcurrency = n 1646 } 1647 1648 // IndexLookupConcurrency return the number of concurrent index lookup worker. 1649 func (c *Concurrency) IndexLookupConcurrency() int { 1650 if c.indexLookupConcurrency != ConcurrencyUnset { 1651 return c.indexLookupConcurrency 1652 } 1653 return c.InterlockingDirectorateConcurrency 1654 } 1655 1656 // IndexLookupJoinConcurrency return the number of concurrent index lookup join inner worker. 1657 func (c *Concurrency) IndexLookupJoinConcurrency() int { 1658 if c.indexLookupJoinConcurrency != ConcurrencyUnset { 1659 return c.indexLookupJoinConcurrency 1660 } 1661 return c.InterlockingDirectorateConcurrency 1662 } 1663 1664 // DistALLEGROSQLScanConcurrency return the number of concurrent dist ALLEGROALLEGROSQL scan worker. 1665 func (c *Concurrency) DistALLEGROSQLScanConcurrency() int { 1666 return c.distALLEGROSQLScanConcurrency 1667 } 1668 1669 // HashJoinConcurrency return the number of concurrent hash join outer worker. 1670 func (c *Concurrency) HashJoinConcurrency() int { 1671 if c.hashJoinConcurrency != ConcurrencyUnset { 1672 return c.hashJoinConcurrency 1673 } 1674 return c.InterlockingDirectorateConcurrency 1675 } 1676 1677 // ProjectionConcurrency return the number of concurrent projection worker. 1678 func (c *Concurrency) ProjectionConcurrency() int { 1679 if c.projectionConcurrency != ConcurrencyUnset { 1680 return c.projectionConcurrency 1681 } 1682 return c.InterlockingDirectorateConcurrency 1683 } 1684 1685 // HashAggPartialConcurrency return the number of concurrent hash aggregation partial worker. 1686 func (c *Concurrency) HashAggPartialConcurrency() int { 1687 if c.hashAggPartialConcurrency != ConcurrencyUnset { 1688 return c.hashAggPartialConcurrency 1689 } 1690 return c.InterlockingDirectorateConcurrency 1691 } 1692 1693 // HashAggFinalConcurrency return the number of concurrent hash aggregation final worker. 1694 func (c *Concurrency) HashAggFinalConcurrency() int { 1695 if c.hashAggFinalConcurrency != ConcurrencyUnset { 1696 return c.hashAggFinalConcurrency 1697 } 1698 return c.InterlockingDirectorateConcurrency 1699 } 1700 1701 // WindowConcurrency return the number of concurrent window worker. 1702 func (c *Concurrency) WindowConcurrency() int { 1703 if c.windowConcurrency != ConcurrencyUnset { 1704 return c.windowConcurrency 1705 } 1706 return c.InterlockingDirectorateConcurrency 1707 } 1708 1709 // IndexSerialScanConcurrency return the number of concurrent index serial scan worker. 1710 // This option is not sync with InterlockingDirectorateConcurrency since it's used by Analyze causet. 1711 func (c *Concurrency) IndexSerialScanConcurrency() int { 1712 return c.indexSerialScanConcurrency 1713 } 1714 1715 // UnionConcurrency return the num of concurrent union worker. 1716 func (c *Concurrency) UnionConcurrency() int { 1717 return c.InterlockingDirectorateConcurrency 1718 } 1719 1720 // MemQuota defines memory quota values. 1721 type MemQuota struct { 1722 // MemQuotaQuery defines the memory quota for a query. 1723 MemQuotaQuery int64 1724 1725 // NestedLoopJoinCacheCapacity defines the memory capacity for apply cache. 1726 NestedLoopJoinCacheCapacity int64 1727 1728 // The variables below do not take any effect anymore, it's remaining for compatibility. 1729 // TODO: remove them in v4.1 1730 // MemQuotaHashJoin defines the memory quota for a hash join interlock. 1731 MemQuotaHashJoin int64 1732 // MemQuotaMergeJoin defines the memory quota for a merge join interlock. 1733 MemQuotaMergeJoin int64 1734 // MemQuotaSort defines the memory quota for a sort interlock. 1735 MemQuotaSort int64 1736 // MemQuotaTopn defines the memory quota for a top n interlock. 1737 MemQuotaTopn int64 1738 // MemQuotaIndexLookupReader defines the memory quota for a index lookup reader interlock. 1739 MemQuotaIndexLookupReader int64 1740 // MemQuotaIndexLookupJoin defines the memory quota for a index lookup join interlock. 1741 MemQuotaIndexLookupJoin int64 1742 // MemQuotaNestedLoopApply defines the memory quota for a nested loop apply interlock. 1743 MemQuotaNestedLoopApply int64 1744 // MemQuotaDistALLEGROSQL defines the memory quota for all operators in DistALLEGROSQL layer like co-processor and selectResult. 1745 MemQuotaDistALLEGROSQL int64 1746 } 1747 1748 // BatchSize defines batch size values. 1749 type BatchSize struct { 1750 // IndexJoinBatchSize is the batch size of a index lookup join. 1751 IndexJoinBatchSize int 1752 1753 // IndexLookupSize is the number of handles for an index lookup task in index double read interlock. 1754 IndexLookupSize int 1755 1756 // InitChunkSize defines init event count of a Chunk during query execution. 1757 InitChunkSize int 1758 1759 // MaxChunkSize defines max event count of a Chunk during query execution. 1760 MaxChunkSize int 1761 } 1762 1763 const ( 1764 // SlowLogRowPrefixStr is slow log event prefix. 1765 SlowLogRowPrefixStr = "# " 1766 // SlowLogSpaceMarkStr is slow log space mark. 1767 SlowLogSpaceMarkStr = ": " 1768 // SlowLogALLEGROSQLSuffixStr is slow log suffix. 1769 SlowLogALLEGROSQLSuffixStr = ";" 1770 // SlowLogTimeStr is slow log field name. 1771 SlowLogTimeStr = "Time" 1772 // SlowLogStartPrefixStr is slow log start event prefix. 1773 SlowLogStartPrefixStr = SlowLogRowPrefixStr + SlowLogTimeStr + SlowLogSpaceMarkStr 1774 // SlowLogTxnStartTSStr is slow log field name. 1775 SlowLogTxnStartTSStr = "Txn_start_ts" 1776 // SlowLogUserAndHostStr is the user and host field name, which is compatible with MyALLEGROSQL. 1777 SlowLogUserAndHostStr = "User@Host" 1778 // SlowLogUserStr is slow log field name. 1779 SlowLogUserStr = "User" 1780 // SlowLogHostStr only for slow_query causet usage. 1781 SlowLogHostStr = "Host" 1782 // SlowLogConnIDStr is slow log field name. 1783 SlowLogConnIDStr = "Conn_ID" 1784 // SlowLogQueryTimeStr is slow log field name. 1785 SlowLogQueryTimeStr = "Query_time" 1786 // SlowLogParseTimeStr is the parse allegrosql time. 1787 SlowLogParseTimeStr = "Parse_time" 1788 // SlowLogCompileTimeStr is the compile plan time. 1789 SlowLogCompileTimeStr = "Compile_time" 1790 // SlowLogRewriteTimeStr is the rewrite time. 1791 SlowLogRewriteTimeStr = "Rewrite_time" 1792 // SlowLogOptimizeTimeStr is the optimization time. 1793 SlowLogOptimizeTimeStr = "Optimize_time" 1794 // SlowLogWaitTSTimeStr is the time of waiting TS. 1795 SlowLogWaitTSTimeStr = "Wait_TS" 1796 // SlowLogPreprocSubQueriesStr is the number of pre-processed sub-queries. 1797 SlowLogPreprocSubQueriesStr = "Preproc_subqueries" 1798 // SlowLogPreProcSubQueryTimeStr is the total time of pre-processing sub-queries. 1799 SlowLogPreProcSubQueryTimeStr = "Preproc_subqueries_time" 1800 // SlowLogDBStr is slow log field name. 1801 SlowLogDBStr = "EDB" 1802 // SlowLogIsInternalStr is slow log field name. 1803 SlowLogIsInternalStr = "Is_internal" 1804 // SlowLogIndexNamesStr is slow log field name. 1805 SlowLogIndexNamesStr = "Index_names" 1806 // SlowLogDigestStr is slow log field name. 1807 SlowLogDigestStr = "Digest" 1808 // SlowLogQueryALLEGROSQLStr is slow log field name. 1809 SlowLogQueryALLEGROSQLStr = "Query" // use for slow log causet, slow log will not print this field name but print allegrosql directly. 1810 // SlowLogStatsInfoStr is plan stats info. 1811 SlowLogStatsInfoStr = "Stats" 1812 // SlowLogNumCausetTasksStr is the number of cop-tasks. 1813 SlowLogNumCausetTasksStr = "Num_cop_tasks" 1814 // SlowLogCopProcAvg is the average process time of all cop-tasks. 1815 SlowLogCopProcAvg = "Cop_proc_avg" 1816 // SlowLogCopProcP90 is the p90 process time of all cop-tasks. 1817 SlowLogCopProcP90 = "Cop_proc_p90" 1818 // SlowLogCopProcMax is the max process time of all cop-tasks. 1819 SlowLogCopProcMax = "Cop_proc_max" 1820 // SlowLogCopProcAddr is the address of EinsteinDB where the cop-task which cost max process time run. 1821 SlowLogCopProcAddr = "Cop_proc_addr" 1822 // SlowLogCopWaitAvg is the average wait time of all cop-tasks. 1823 SlowLogCopWaitAvg = "Cop_wait_avg" 1824 // SlowLogCopWaitP90 is the p90 wait time of all cop-tasks. 1825 SlowLogCopWaitP90 = "Cop_wait_p90" 1826 // SlowLogCopWaitMax is the max wait time of all cop-tasks. 1827 SlowLogCopWaitMax = "Cop_wait_max" 1828 // SlowLogCopWaitAddr is the address of EinsteinDB where the cop-task which cost wait process time run. 1829 SlowLogCopWaitAddr = "Cop_wait_addr" 1830 // SlowLogCopBackoffPrefix contains backoff information. 1831 SlowLogCopBackoffPrefix = "Cop_backoff_" 1832 // SlowLogMemMax is the max number bytes of memory used in this memex. 1833 SlowLogMemMax = "Mem_max" 1834 // SlowLogDiskMax is the nax number bytes of disk used in this memex. 1835 SlowLogDiskMax = "Disk_max" 1836 // SlowLogPrepared is used to indicate whether this allegrosql execute in prepare. 1837 SlowLogPrepared = "Prepared" 1838 // SlowLogCausetFromCache is used to indicate whether this plan is from plan cache. 1839 SlowLogCausetFromCache = "Causet_from_cache" 1840 // SlowLogHasMoreResults is used to indicate whether this allegrosql has more following results. 1841 SlowLogHasMoreResults = "Has_more_results" 1842 // SlowLogSucc is used to indicate whether this allegrosql execute successfully. 1843 SlowLogSucc = "Succ" 1844 // SlowLogPrevStmt is used to show the previous executed memex. 1845 SlowLogPrevStmt = "Prev_stmt" 1846 // SlowLogCauset is used to record the query plan. 1847 SlowLogCauset = "Causet" 1848 // SlowLogCausetDigest is used to record the query plan digest. 1849 SlowLogCausetDigest = "Causet_digest" 1850 // SlowLogCausetPrefix is the prefix of the plan value. 1851 SlowLogCausetPrefix = ast.MilevaDBDecodeCauset + "('" 1852 // SlowLogCausetSuffix is the suffix of the plan value. 1853 SlowLogCausetSuffix = "')" 1854 // SlowLogPrevStmtPrefix is the prefix of Prev_stmt in slow log file. 1855 SlowLogPrevStmtPrefix = SlowLogPrevStmt + SlowLogSpaceMarkStr 1856 // SlowLogKVTotal is the total time waiting for ekv. 1857 SlowLogKVTotal = "KV_total" 1858 // SlowLogFIDelTotal is the total time waiting for fidel. 1859 SlowLogFIDelTotal = "FIDel_total" 1860 // SlowLogBackoffTotal is the total time doing backoff. 1861 SlowLogBackoffTotal = "Backoff_total" 1862 // SlowLogWriteALLEGROSQLRespTotal is the total time used to write response to client. 1863 SlowLogWriteALLEGROSQLRespTotal = "Write_sql_response_total" 1864 // SlowLogInterDircRetryCount is the execution retry count. 1865 SlowLogInterDircRetryCount = "InterDirc_retry_count" 1866 // SlowLogInterDircRetryTime is the execution retry time. 1867 SlowLogInterDircRetryTime = "InterDirc_retry_time" 1868 ) 1869 1870 // SlowQueryLogItems is a defCauslection of items that should be included in the 1871 // slow query log. 1872 type SlowQueryLogItems struct { 1873 TxnTS uint64 1874 ALLEGROALLEGROSQL string 1875 Digest string 1876 TimeTotal time.Duration 1877 TimeParse time.Duration 1878 TimeCompile time.Duration 1879 TimeOptimize time.Duration 1880 TimeWaitTS time.Duration 1881 IndexNames string 1882 StatsInfos map[string]uint64 1883 CausetTasks *stmtctx.CausetTasksDetails 1884 InterDircDetail execdetails.InterDircDetails 1885 MemMax int64 1886 DiskMax int64 1887 Succ bool 1888 Prepared bool 1889 CausetFromCache bool 1890 HasMoreResults bool 1891 PrevStmt string 1892 Causet string 1893 CausetDigest string 1894 RewriteInfo RewritePhaseInfo 1895 KVTotal time.Duration 1896 FIDelTotal time.Duration 1897 BackoffTotal time.Duration 1898 WriteALLEGROSQLRespTotal time.Duration 1899 InterDircRetryCount uint 1900 InterDircRetryTime time.Duration 1901 } 1902 1903 // SlowLogFormat uses for formatting slow log. 1904 // The slow log output is like below: 1905 // # Time: 2020-04-28T15:24:04.309074+08:00 1906 // # Txn_start_ts: 406315658548871171 1907 // # User@Host: root[root] @ localhost [127.0.0.1] 1908 // # Conn_ID: 6 1909 // # Query_time: 4.895492 1910 // # Process_time: 0.161 Request_count: 1 Total_keys: 100001 Processed_keys: 100000 1911 // # EDB: test 1912 // # Index_names: [t1.idx1,t2.idx2] 1913 // # Is_internal: false 1914 // # Digest: 42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772 1915 // # Stats: t1:1,t2:2 1916 // # Num_cop_tasks: 10 1917 // # Cop_process: Avg_time: 1s P90_time: 2s Max_time: 3s Max_addr: 10.6.131.78 1918 // # Cop_wait: Avg_time: 10ms P90_time: 20ms Max_time: 30ms Max_Addr: 10.6.131.79 1919 // # Memory_max: 4096 1920 // # Disk_max: 65535 1921 // # Succ: true 1922 // # Prev_stmt: begin; 1923 // select * from t_slim; 1924 func (s *StochastikVars) SlowLogFormat(logItems *SlowQueryLogItems) string { 1925 var buf bytes.Buffer 1926 1927 writeSlowLogItem(&buf, SlowLogTxnStartTSStr, strconv.FormatUint(logItems.TxnTS, 10)) 1928 if s.User != nil { 1929 hostAddress := s.User.Hostname 1930 if s.ConnectionInfo != nil { 1931 hostAddress = s.ConnectionInfo.ClientIP 1932 } 1933 writeSlowLogItem(&buf, SlowLogUserAndHostStr, fmt.Sprintf("%s[%s] @ %s [%s]", s.User.Username, s.User.Username, s.User.Hostname, hostAddress)) 1934 } 1935 if s.ConnectionID != 0 { 1936 writeSlowLogItem(&buf, SlowLogConnIDStr, strconv.FormatUint(s.ConnectionID, 10)) 1937 } 1938 if logItems.InterDircRetryCount > 0 { 1939 buf.WriteString(SlowLogRowPrefixStr) 1940 buf.WriteString(SlowLogInterDircRetryTime) 1941 buf.WriteString(SlowLogSpaceMarkStr) 1942 buf.WriteString(strconv.FormatFloat(logItems.InterDircRetryTime.Seconds(), 'f', -1, 64)) 1943 buf.WriteString(" ") 1944 buf.WriteString(SlowLogInterDircRetryCount) 1945 buf.WriteString(SlowLogSpaceMarkStr) 1946 buf.WriteString(strconv.Itoa(int(logItems.InterDircRetryCount))) 1947 buf.WriteString("\n") 1948 } 1949 writeSlowLogItem(&buf, SlowLogQueryTimeStr, strconv.FormatFloat(logItems.TimeTotal.Seconds(), 'f', -1, 64)) 1950 writeSlowLogItem(&buf, SlowLogParseTimeStr, strconv.FormatFloat(logItems.TimeParse.Seconds(), 'f', -1, 64)) 1951 writeSlowLogItem(&buf, SlowLogCompileTimeStr, strconv.FormatFloat(logItems.TimeCompile.Seconds(), 'f', -1, 64)) 1952 1953 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v", SlowLogRewriteTimeStr, 1954 SlowLogSpaceMarkStr, strconv.FormatFloat(logItems.RewriteInfo.DurationRewrite.Seconds(), 'f', -1, 64))) 1955 if logItems.RewriteInfo.PreprocessSubQueries > 0 { 1956 buf.WriteString(fmt.Sprintf(" %v%v%v %v%v%v", SlowLogPreprocSubQueriesStr, SlowLogSpaceMarkStr, logItems.RewriteInfo.PreprocessSubQueries, 1957 SlowLogPreProcSubQueryTimeStr, SlowLogSpaceMarkStr, strconv.FormatFloat(logItems.RewriteInfo.DurationPreprocessSubQuery.Seconds(), 'f', -1, 64))) 1958 } 1959 buf.WriteString("\n") 1960 1961 writeSlowLogItem(&buf, SlowLogOptimizeTimeStr, strconv.FormatFloat(logItems.TimeOptimize.Seconds(), 'f', -1, 64)) 1962 writeSlowLogItem(&buf, SlowLogWaitTSTimeStr, strconv.FormatFloat(logItems.TimeWaitTS.Seconds(), 'f', -1, 64)) 1963 1964 if execDetailStr := logItems.InterDircDetail.String(); len(execDetailStr) > 0 { 1965 buf.WriteString(SlowLogRowPrefixStr + execDetailStr + "\n") 1966 } 1967 1968 if len(s.CurrentDB) > 0 { 1969 writeSlowLogItem(&buf, SlowLogDBStr, s.CurrentDB) 1970 } 1971 if len(logItems.IndexNames) > 0 { 1972 writeSlowLogItem(&buf, SlowLogIndexNamesStr, logItems.IndexNames) 1973 } 1974 1975 writeSlowLogItem(&buf, SlowLogIsInternalStr, strconv.FormatBool(s.InRestrictedALLEGROSQL)) 1976 if len(logItems.Digest) > 0 { 1977 writeSlowLogItem(&buf, SlowLogDigestStr, logItems.Digest) 1978 } 1979 if len(logItems.StatsInfos) > 0 { 1980 buf.WriteString(SlowLogRowPrefixStr + SlowLogStatsInfoStr + SlowLogSpaceMarkStr) 1981 firstComma := false 1982 vStr := "" 1983 for k, v := range logItems.StatsInfos { 1984 if v == 0 { 1985 vStr = "pseudo" 1986 } else { 1987 vStr = strconv.FormatUint(v, 10) 1988 1989 } 1990 if firstComma { 1991 buf.WriteString("," + k + ":" + vStr) 1992 } else { 1993 buf.WriteString(k + ":" + vStr) 1994 firstComma = true 1995 } 1996 } 1997 buf.WriteString("\n") 1998 } 1999 if logItems.CausetTasks != nil { 2000 writeSlowLogItem(&buf, SlowLogNumCausetTasksStr, strconv.FormatInt(int64(logItems.CausetTasks.NumCausetTasks), 10)) 2001 if logItems.CausetTasks.NumCausetTasks > 0 { 2002 // make the result sblock 2003 backoffs := make([]string, 0, 3) 2004 for backoff := range logItems.CausetTasks.TotBackoffTimes { 2005 backoffs = append(backoffs, backoff) 2006 } 2007 sort.Strings(backoffs) 2008 2009 if logItems.CausetTasks.NumCausetTasks == 1 { 2010 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v", 2011 SlowLogCopProcAvg, SlowLogSpaceMarkStr, logItems.CausetTasks.AvgProcessTime.Seconds(), 2012 SlowLogCopProcAddr, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxProcessAddress) + "\n") 2013 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v", 2014 SlowLogCopWaitAvg, SlowLogSpaceMarkStr, logItems.CausetTasks.AvgWaitTime.Seconds(), 2015 SlowLogCopWaitAddr, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxWaitAddress) + "\n") 2016 for _, backoff := range backoffs { 2017 backoffPrefix := SlowLogCopBackoffPrefix + backoff + "_" 2018 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v\n", 2019 backoffPrefix+"total_times", SlowLogSpaceMarkStr, logItems.CausetTasks.TotBackoffTimes[backoff], 2020 backoffPrefix+"total_time", SlowLogSpaceMarkStr, logItems.CausetTasks.TotBackoffTime[backoff].Seconds(), 2021 )) 2022 } 2023 } else { 2024 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v %v%v%v %v%v%v", 2025 SlowLogCopProcAvg, SlowLogSpaceMarkStr, logItems.CausetTasks.AvgProcessTime.Seconds(), 2026 SlowLogCopProcP90, SlowLogSpaceMarkStr, logItems.CausetTasks.P90ProcessTime.Seconds(), 2027 SlowLogCopProcMax, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxProcessTime.Seconds(), 2028 SlowLogCopProcAddr, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxProcessAddress) + "\n") 2029 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v %v%v%v %v%v%v", 2030 SlowLogCopWaitAvg, SlowLogSpaceMarkStr, logItems.CausetTasks.AvgWaitTime.Seconds(), 2031 SlowLogCopWaitP90, SlowLogSpaceMarkStr, logItems.CausetTasks.P90WaitTime.Seconds(), 2032 SlowLogCopWaitMax, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxWaitTime.Seconds(), 2033 SlowLogCopWaitAddr, SlowLogSpaceMarkStr, logItems.CausetTasks.MaxWaitAddress) + "\n") 2034 for _, backoff := range backoffs { 2035 backoffPrefix := SlowLogCopBackoffPrefix + backoff + "_" 2036 buf.WriteString(SlowLogRowPrefixStr + fmt.Sprintf("%v%v%v %v%v%v %v%v%v %v%v%v %v%v%v %v%v%v\n", 2037 backoffPrefix+"total_times", SlowLogSpaceMarkStr, logItems.CausetTasks.TotBackoffTimes[backoff], 2038 backoffPrefix+"total_time", SlowLogSpaceMarkStr, logItems.CausetTasks.TotBackoffTime[backoff].Seconds(), 2039 backoffPrefix+"max_time", SlowLogSpaceMarkStr, logItems.CausetTasks.MaxBackoffTime[backoff].Seconds(), 2040 backoffPrefix+"max_addr", SlowLogSpaceMarkStr, logItems.CausetTasks.MaxBackoffAddress[backoff], 2041 backoffPrefix+"avg_time", SlowLogSpaceMarkStr, logItems.CausetTasks.AvgBackoffTime[backoff].Seconds(), 2042 backoffPrefix+"p90_time", SlowLogSpaceMarkStr, logItems.CausetTasks.P90BackoffTime[backoff].Seconds(), 2043 )) 2044 } 2045 } 2046 } 2047 } 2048 if logItems.MemMax > 0 { 2049 writeSlowLogItem(&buf, SlowLogMemMax, strconv.FormatInt(logItems.MemMax, 10)) 2050 } 2051 if logItems.DiskMax > 0 { 2052 writeSlowLogItem(&buf, SlowLogDiskMax, strconv.FormatInt(logItems.DiskMax, 10)) 2053 } 2054 2055 writeSlowLogItem(&buf, SlowLogPrepared, strconv.FormatBool(logItems.Prepared)) 2056 writeSlowLogItem(&buf, SlowLogCausetFromCache, strconv.FormatBool(logItems.CausetFromCache)) 2057 writeSlowLogItem(&buf, SlowLogHasMoreResults, strconv.FormatBool(logItems.HasMoreResults)) 2058 writeSlowLogItem(&buf, SlowLogKVTotal, strconv.FormatFloat(logItems.KVTotal.Seconds(), 'f', -1, 64)) 2059 writeSlowLogItem(&buf, SlowLogFIDelTotal, strconv.FormatFloat(logItems.FIDelTotal.Seconds(), 'f', -1, 64)) 2060 writeSlowLogItem(&buf, SlowLogBackoffTotal, strconv.FormatFloat(logItems.BackoffTotal.Seconds(), 'f', -1, 64)) 2061 writeSlowLogItem(&buf, SlowLogWriteALLEGROSQLRespTotal, strconv.FormatFloat(logItems.WriteALLEGROSQLRespTotal.Seconds(), 'f', -1, 64)) 2062 writeSlowLogItem(&buf, SlowLogSucc, strconv.FormatBool(logItems.Succ)) 2063 if len(logItems.Causet) != 0 { 2064 writeSlowLogItem(&buf, SlowLogCauset, logItems.Causet) 2065 } 2066 if len(logItems.CausetDigest) != 0 { 2067 writeSlowLogItem(&buf, SlowLogCausetDigest, logItems.CausetDigest) 2068 } 2069 2070 if logItems.PrevStmt != "" { 2071 writeSlowLogItem(&buf, SlowLogPrevStmt, logItems.PrevStmt) 2072 } 2073 2074 if s.CurrentDBChanged { 2075 buf.WriteString(fmt.Sprintf("use %s;\n", s.CurrentDB)) 2076 s.CurrentDBChanged = false 2077 } 2078 2079 buf.WriteString(logItems.ALLEGROALLEGROSQL) 2080 if len(logItems.ALLEGROALLEGROSQL) == 0 || logItems.ALLEGROALLEGROSQL[len(logItems.ALLEGROALLEGROSQL)-1] != ';' { 2081 buf.WriteString(";") 2082 } 2083 return buf.String() 2084 } 2085 2086 // writeSlowLogItem writes a slow log item in the form of: "# ${key}:${value}" 2087 func writeSlowLogItem(buf *bytes.Buffer, key, value string) { 2088 buf.WriteString(SlowLogRowPrefixStr + key + SlowLogSpaceMarkStr + value + "\n") 2089 }