-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for MAX_EXECUTION_TIME. #10541
Add support for MAX_EXECUTION_TIME. #10541
Conversation
Codecov Report
@@ Coverage Diff @@
## master #10541 +/- ##
================================================
- Coverage 81.3393% 81.1436% -0.1957%
================================================
Files 419 419
Lines 90002 89153 -849
================================================
- Hits 73207 72342 -865
- Misses 11546 11563 +17
+ Partials 5249 5248 -1 |
server/conn.go
Outdated
//MaxExecDuration() return 0 if there is no limit | ||
if rs.MaxExecDuration().Nanoseconds() > 0 && | ||
time.Now().After(rs.StartExecTime().Add(rs.MaxExecDuration())) { | ||
return errors.New("Query execution was interrupted, max_execution_time exceeded") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an standard error code for this type of error in MySQL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the execution is blocked at line 1311 for a long time, it may exceed the maxExecDuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an standard error code for this type of error in MySQL?
Error code 1907 added to parser, refer to PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the execution is blocked at line 1311 for a long time, it may exceed the maxExecDuration.
Fixed by closing result set and context on timeout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is better to use this predefined error in parser repo,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is better to use this predefined error in parser repo,
OK, I will add and use the error code.
By the way, should all published Mysql error codes be imported in batch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, it will be defined when it is used.
I think this should also be pushed down to TiKV to support per-statement max execution time limit. |
server/conn.go
Outdated
//MaxExecDuration() return 0 if there is no limit | ||
if rs.MaxExecDuration().Nanoseconds() > 0 && | ||
time.Now().After(rs.StartExecTime().Add(rs.MaxExecDuration())) { | ||
return errors.New("Query execution was interrupted, max_execution_time exceeded") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this cannot work for cases like HashAgg
which consumes all of its child's input and finally returns result?
We can do this later after finishing |
code changed per review comments, please review again. |
@db-storage please fix CI problems and resolve conflicts. |
So many unrelated changes in this PR, maybe need a squash. |
The last committed code depends on Error Code defined in parser, refer to PR. I will resolve conflicts and do a squash. |
b9f7706
to
4f272e8
Compare
This commit use context cancel to implement MAX_EXECUTION_TIME. Cancel context is the way we used to implement
In commit #9844, we turn to use In this PR #10350, there is a background goroutine that monitoring all slow queries, maybe it's better to wait the PR to be merged and implement MAX_EXECUTION_TIME after that. |
recordSet.Close() is called too when the execution is timed out.
I can't find
In order to use the same go routine? when will PR #10350 be merged? |
Yes, 'resultSet.Close'
In order to make the code easier to maintain ... add a monitoring goroutine is a more general solution @XuHuaiyu will take charge of that PR and I guess it won't be too long get merged |
a1f7962
to
2f9d152
Compare
@db-storage Please resolve the conflicts. |
- Use existing slow query handler to monitor registered queries; - Don't use resultSet's CancelFunc, use Close only; - Add error errMaxExecTimeExceeded; - Modify writeChunk, don't send EOF if execution timed out.
2f9d152
to
e9e5222
Compare
Conflicts solved. `mysql> select /+ MAX_EXECUTION_TIME(100)/ * from litong where SLEEP(2) and exists (select * from test3 where test3.num>=litong.num); mysql> select * from litong; |
…e bug. 'make all' passed.
sessionctx/variable/tidb_vars.go
Outdated
@@ -334,7 +334,8 @@ const ( | |||
DefTiDBUseFastAnalyze = false | |||
DefTiDBSkipIsolationLevelCheck = false | |||
DefTiDBWaitTableSplitFinish = false | |||
DefTiDBExpensiveQueryTimeThreshold = 60 // 60s | |||
DefTiDBExpensiveQueryTimeThreshold = 100 // 100 ms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100ms is too small as the default value for ExpensiveQueryTimeThreshold
, it makes TiDB print a log of logs.
I think 60s may be a better default value here.
And note that the check interval of the ticker is not necessary to be ExpensiveQueryTimeThreshold / 2
because the check interval value is shared with MAX_EXECUTION_TIME
check interval, maybe 100ms is a good choice.
It means the MAX_EXECUTION_TIME
will be less accurate if the check interval is 100ms. That's acceptable as the code is simple enough in my opinion. We can polish the code after this feature is merged, adopting a dynamic check interval.
…rval in ExpensiveQueryTimeThreshold; 'make all' passed
sessionctx/variable/session.go
Outdated
@@ -682,6 +686,12 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { | |||
if isAutocommit { | |||
s.SetStatusFlag(mysql.ServerStatusInTrans, false) | |||
} | |||
case MaxExecutionTime: | |||
timeoutMS := tidbOptInt64(val, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about use tidbOptPositiveInt32
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/run-all-tests |
/run-all-tests |
Did we? @zhangjinpeng1987 |
What problem does this PR solve?
Fixes #7008
What is changed and how it works?
Check List
Tests
`mysql> select /+ MAX_EXECUTION_TIME(100)/ * from litong where SLEEP(2) and exists (select * from test3 where test3.num>=litong.num);
ERROR 1907 (HY000): Query execution was interrupted, max_execution_time exceeded.
mysql> select * from litong where SLEEP(2);
Empty set (4.00 sec)
mysql> select * from litong;
+-----+------+
| id | num |
+-----+------+
| 100 | 28 |
| 101 | 28 |
+-----+------+
2 rows in set (0.00 sec)`
Code changes
Side effects
Related changes