-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
*: Reduce loading schema times #1984
Conversation
} | ||
do.SchemaValidity.setLastFailedTS(ver.Ver) | ||
log.Errorf("[ddl] load schema err %v, retry again", errors.ErrorStack(err)) | ||
if atomic.LoadInt32(exit) == 1 { |
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.
this is not Go-style, I suggest make exit
a channel:
select {
case <-timeout:
case <-exit:
}
var defaultMinReloadTimeout = 20 * time.Second | ||
|
||
// Reload reloads InfoSchema. | ||
func (do *Domain) Reload() error { | ||
func (do *Domain) reload() error { | ||
// for test | ||
if do.SchemaValidity.MockReloadFailed { |
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.
mixing the test code logic would hurt readability, can you find better way to do it?
such as extract to an interface and wrap the mocked code upon the real implementation
log.Errorf("[ddl] reload schema in loop err %v", errors.ErrorStack(err)) | ||
time.Sleep(mustReloadSleepTime) |
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.
after the time.Sleep
, it would miss the do.leaseCh
signal for a while, would this cause problem?
c.Assert(dd.GetLease(), Equals, 100*time.Millisecond) | ||
dom.SetLease(0 * time.Millisecond) | ||
c.Assert(dd.GetLease(), Equals, 100*time.Millisecond) | ||
time.Sleep(100 * time.Millisecond) |
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.
what's the purpose of this line?
0fb9dc0
to
5bd5a13
Compare
5bd5a13
to
e29e0e7
Compare
e29e0e7
to
897715d
Compare
} | ||
|
||
return errors.Trace(err) | ||
} | ||
|
||
// MustReload reloads the infoschema. | ||
// If reload error, it will hold whole program to guarantee data safe. | ||
// It's public in order to do the test. | ||
func (do *Domain) MustReload() error { |
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.
MustReload
does nothing more than reload
. We can remove this function, use reload
instead.
6e503b8
to
8af9fba
Compare
PTAL @coocood @tiancaiamao @shenli |
…zimuxia/domain-reload Conflicts: store/tikv/store_test.go
return | ||
log.Infof("[ddl] check validity in a loop, sub:%v, lease:%v, succ:%v, waitTime:%v", | ||
sub, lease, lastSuccTS, waitTime) | ||
timer.Reset(waitTime) |
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.
This is not the ideal usage of timer.Reset
see https://godoc.org/time#Timer.Reset
To reuse an active timer, always call its Stop method first and—if it had expired—drain the value from its channel.
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.
Here doesn't need to add that judgment.
do.SchemaValidity.SetValidity(false) | ||
return errors.Trace(err) | ||
lease = newLease | ||
timer.Reset(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.
I think line 344~350 can just one line:
lease = newLease
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.
I don‘t want to wait a old lease
ticker := time.NewTicker(lease) | ||
defer ticker.Stop() | ||
ticker := time.NewTicker(lease / 4) | ||
defer func() { ticker.Stop() }() |
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.
defer ticker.Stop()
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.
Because ticker is reassigned in line 375 . It can prevent panic.
} | ||
|
||
func (do *Domain) loadSchemaInLoop(lease time.Duration) { | ||
ticker := time.NewTicker(lease) |
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.
the code is misleading, I suggest set lease / 4
outside...
let caller do it instead of callee
|
||
// Reload reloads InfoSchema. | ||
// It's public in order to do the test. | ||
func (do *Domain) Reload() error { |
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.
I think sleep and retry in Reload is not a good idea.
There would be new ticker signal happen during this, and may cause Reload be called several times.
A better way is reload returns error and let loadSchemaInLoop
handle the retry.
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.
Reload will return an error.
} | ||
|
||
// SetValidity sets the schema validity value. | ||
// It's public in order to do the test. | ||
func (s *schemaValidityInfo) SetValidity(v bool) { | ||
func (s *schemaValidityInfo) SetValidity(v bool, lastSuccTS uint64) { |
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.
Can we remove the lastSuccTS
parameter, and set s.firstValidTS = s.lastSuccTS
directly?
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.
Setting s.firstValidTS = s.lastSuccTS
may be concurrent.
ticker := time.NewTicker(lease) | ||
defer ticker.Stop() | ||
ticker := time.NewTicker(minInterval(lease)) | ||
defer func() { ticker.Stop() }() |
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.
I will deal with it in the next PR.
PTAL @tiancaiamao @coocood |
LGTM |
}() | ||
|
||
wg.Wait() | ||
|
||
// retry after 2 seconds | ||
time.Sleep(2000 * time.Millisecond) |
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 seems server is busy just 60ms, is it necessary sleep so long here?
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 server is busy, transaction will retry after 2s.
LGTM |
PTAL @disksing |
1432c16
to
ab32b51
Compare
Only if it's success to do DDL or in reloadLoop to load schema
Update code
Improve test coverage from 65% to 75%
fix Make sure lastInvalidTS is a normal txn TS. #1571