Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3569fb0
*: avoid notify privilege update for all users
tiancaiamao Oct 31, 2024
4f3fcad
fix build
tiancaiamao Nov 1, 2024
dcd2095
fix CI
tiancaiamao Nov 1, 2024
529716a
append+sort+dedup does not work for delete record
tiancaiamao Nov 4, 2024
b545ab6
make lint happy
tiancaiamao Nov 4, 2024
cf1c7b5
fix integration test
tiancaiamao Nov 5, 2024
ba6c578
match resource group
tiancaiamao Nov 5, 2024
de42e04
Merge branch 'master' into notify-update
tiancaiamao Nov 6, 2024
e473466
loadSomeUser now load the user's role first
tiancaiamao Nov 6, 2024
fbdc2e8
make lint check happy
tiancaiamao Nov 6, 2024
1b7ac08
fix test case TestFailedLoginTrackingBasic
tiancaiamao Nov 7, 2024
363f6af
make lint happy
tiancaiamao Nov 7, 2024
d54cd58
fix TestDefaultRoles
tiancaiamao Nov 7, 2024
3c89902
fix TestSandBoxMode
tiancaiamao Nov 7, 2024
20cbbcc
fix build
tiancaiamao Nov 7, 2024
8cc9d34
Merge branch 'master' into notify-update
tiancaiamao Nov 7, 2024
a91270b
fix TestAuthPlugin
tiancaiamao Nov 7, 2024
e061798
the role of an active user should also be consider active
tiancaiamao Nov 8, 2024
fc7589e
address comment
tiancaiamao Nov 11, 2024
9ff7c7a
Merge branch 'master' into notify-update
tiancaiamao Nov 11, 2024
fe21eee
address comment
tiancaiamao Nov 14, 2024
66542b8
make fmt
tiancaiamao Nov 18, 2024
db9a92d
address comment
tiancaiamao Nov 18, 2024
f0ee13a
address comment
tiancaiamao Nov 20, 2024
54c2e1a
make bazel_prepare
tiancaiamao Nov 20, 2024
2ea8cdd
make lint happy
tiancaiamao Nov 20, 2024
60bc7f6
make lint happy
tiancaiamao Nov 20, 2024
13b5a91
make lint happy
tiancaiamao Nov 20, 2024
badb6ab
Merge branch 'master' into notify-update
tiancaiamao Nov 20, 2024
5b0db78
fix CI
tiancaiamao Nov 20, 2024
57a9275
address comment
tiancaiamao Nov 21, 2024
6558e49
address comment
tiancaiamao Nov 21, 2024
a187c8a
Update pkg/privilege/privileges/cache.go
tiancaiamao Nov 21, 2024
99cd464
address comment
tiancaiamao Nov 21, 2024
f60c509
Update pkg/domain/domain.go
tiancaiamao Nov 28, 2024
2386758
address comment
tiancaiamao Nov 28, 2024
c184096
Merge branch 'master' into notify-update
tiancaiamao Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion br/pkg/restore/snap_client/systable_restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (rc *SnapClient) afterSystemTablesReplaced(ctx context.Context, db string,
var err error
for _, table := range tables {
if table == "user" {
if serr := rc.dom.NotifyUpdatePrivilege(); serr != nil {
if serr := rc.dom.NotifyUpdateAllUsersPrivilege(); serr != nil {
log.Warn("failed to flush privileges, please manually execute `FLUSH PRIVILEGES`")
err = multierr.Append(err, berrors.ErrUnknown.Wrap(serr).GenWithStack("failed to flush privileges"))
} else {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ddl/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6088,7 +6088,7 @@ func (e *executor) DropResourceGroup(ctx sessionctx.Context, stmt *ast.DropResou
if checker == nil {
return errors.New("miss privilege checker")
}
user, matched := checker.MatchUserResourceGroupName(groupName.L)
user, matched := checker.MatchUserResourceGroupName(ctx.GetRestrictedSQLExecutor(), groupName.L)
if matched {
err = errors.Errorf("user [%s] depends on the resource group to drop", user)
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ go_library(
"//pkg/util/printer",
"//pkg/util/replayer",
"//pkg/util/servermemorylimit",
"//pkg/util/size",
"//pkg/util/sqlexec",
"//pkg/util/sqlkiller",
"//pkg/util/syncutil",
Expand Down
102 changes: 84 additions & 18 deletions pkg/domain/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package domain

import (
"context"
"encoding/json"
"fmt"
"math"
"math/rand"
Expand Down Expand Up @@ -94,6 +95,7 @@ import (
"github.com/pingcap/tidb/pkg/util/memoryusagealarm"
"github.com/pingcap/tidb/pkg/util/replayer"
"github.com/pingcap/tidb/pkg/util/servermemorylimit"
"github.com/pingcap/tidb/pkg/util/size"
"github.com/pingcap/tidb/pkg/util/sqlkiller"
"github.com/pingcap/tidb/pkg/util/syncutil"
"github.com/tikv/client-go/v2/tikv"
Expand Down Expand Up @@ -1808,6 +1810,36 @@ func (do *Domain) GetPDHTTPClient() pdhttp.Client {
return nil
}

func decodePrivilegeEvent(resp clientv3.WatchResponse) PrivilegeEvent {
var msg PrivilegeEvent
for _, event := range resp.Events {
if event.Kv != nil {
val := event.Kv.Value
if len(val) > 0 {
var tmp PrivilegeEvent
err := json.Unmarshal(val, &tmp)
if err != nil {
logutil.BgLogger().Warn("decodePrivilegeEvent unmarshal fail", zap.Error(err))
break
}
if tmp.All {
msg.All = true
break
}
// duplicated users in list is ok.
msg.UserList = append(msg.UserList, tmp.UserList...)
}
}
}

// In case old version triggers the event, the event value is empty,
// Then we fall back to the old way: reload all the users.
if len(msg.UserList) == 0 {
Comment thread
tiancaiamao marked this conversation as resolved.
msg.All = true
}
return msg
}

// LoadPrivilegeLoop create a goroutine loads privilege tables in a loop, it
// should be called only once in BootstrapSession.
func (do *Domain) LoadPrivilegeLoop(sctx sessionctx.Context) error {
Expand All @@ -1822,7 +1854,7 @@ func (do *Domain) LoadPrivilegeLoop(sctx sessionctx.Context) error {
var watchCh clientv3.WatchChan
duration := 5 * time.Minute
if do.etcdClient != nil {
watchCh = do.etcdClient.Watch(context.Background(), privilegeKey)
watchCh = do.etcdClient.Watch(do.ctx, privilegeKey)
Comment thread
D3Hunter marked this conversation as resolved.
duration = 10 * time.Minute
}

Expand All @@ -1834,25 +1866,32 @@ func (do *Domain) LoadPrivilegeLoop(sctx sessionctx.Context) error {

var count int
for {
ok := true
var err error
select {
case <-do.exit:
return
case _, ok = <-watchCh:
case <-time.After(duration):
}
if !ok {
logutil.BgLogger().Error("load privilege loop watch channel closed")
watchCh = do.etcdClient.Watch(context.Background(), privilegeKey)
count++
if count > 10 {
time.Sleep(time.Duration(count) * time.Second)
case resp, ok := <-watchCh:
if ok {
Comment thread
tiancaiamao marked this conversation as resolved.
count = 0
event := decodePrivilegeEvent(resp)
if event.All {
err = do.privHandle.UpdateAll()
} else {
err = do.privHandle.Update(event.UserList)
}
} else {
if do.ctx.Err() == nil {
logutil.BgLogger().Error("load privilege loop watch channel closed")
watchCh = do.etcdClient.Watch(do.ctx, privilegeKey)
count++
if count > 10 {
time.Sleep(time.Duration(count) * time.Second)
}
}
}
continue
case <-time.After(duration):
err = do.privHandle.UpdateAll()
}
Comment thread
tiancaiamao marked this conversation as resolved.

count = 0
err := do.privHandle.Update()
metrics.LoadPrivilegeCounter.WithLabelValues(metrics.RetLabel(err)).Inc()
if err != nil {
logutil.BgLogger().Error("load privilege failed", zap.Error(err))
Expand Down Expand Up @@ -2751,15 +2790,39 @@ const (
tiflashComputeNodeKey = "/tiflash/new_tiflash_compute_nodes"
)

// PrivilegeEvent is the message definition for NotifyUpdatePrivilege(), encoded in json.
// TiDB old version do not use no such message.
type PrivilegeEvent struct {
All bool
UserList []string
}

// NotifyUpdateAllUsersPrivilege updates privilege key in etcd, TiDB client that watches
// the key will get notification.
func (do *Domain) NotifyUpdateAllUsersPrivilege() error {
return do.notifyUpdatePrivilege(PrivilegeEvent{All: true})
}

// NotifyUpdatePrivilege updates privilege key in etcd, TiDB client that watches
// the key will get notification.
func (do *Domain) NotifyUpdatePrivilege() error {
func (do *Domain) NotifyUpdatePrivilege(userList []string) error {
return do.notifyUpdatePrivilege(PrivilegeEvent{UserList: userList})
}

func (do *Domain) notifyUpdatePrivilege(event PrivilegeEvent) error {
// No matter skip-grant-table is configured or not, sending an etcd message is required.
// Because we need to tell other TiDB instances to update privilege data, say, we're changing the
// password using a special TiDB instance and want the new password to take effect.
if do.etcdClient != nil {
data, err := json.Marshal(event)
if err != nil {
return errors.Trace(err)
}
if uint64(len(data)) > size.MB {
logutil.BgLogger().Warn("notify update privilege message too large", zap.ByteString("value", data))
}
row := do.etcdClient.KV
_, err := row.Put(context.Background(), privilegeKey, "")
_, err = row.Put(do.ctx, privilegeKey, string(data))
if err != nil {
logutil.BgLogger().Warn("notify update privilege failed", zap.Error(err))
}
Expand All @@ -2772,7 +2835,10 @@ func (do *Domain) NotifyUpdatePrivilege() error {
return nil
}

return do.PrivilegeHandle().Update()
if event.All {
return do.PrivilegeHandle().UpdateAll()
}
return do.PrivilegeHandle().Update(event.UserList)
}

// NotifyUpdateSysVarCache updates the sysvar cache key in etcd, which other TiDB
Expand Down
3 changes: 2 additions & 1 deletion pkg/executor/grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ func (e *GrantExec) Next(ctx context.Context, _ *chunk.Chunk) error {
return err
}
isCommit = true
return domain.GetDomain(e.Ctx()).NotifyUpdatePrivilege()
users := userSpecToUserList(e.Users)
return domain.GetDomain(e.Ctx()).NotifyUpdatePrivilege(users)
}

func containsNonDynamicPriv(privList []*ast.PrivElem) bool {
Expand Down
11 changes: 10 additions & 1 deletion pkg/executor/revoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,16 @@ func (e *RevokeExec) Next(ctx context.Context, _ *chunk.Chunk) error {
return err
}
isCommit = true
return domain.GetDomain(e.Ctx()).NotifyUpdatePrivilege()
users := userSpecToUserList(e.Users)
return domain.GetDomain(e.Ctx()).NotifyUpdatePrivilege(users)
}

func userSpecToUserList(specs []*ast.UserSpec) []string {
users := make([]string, 0, len(specs))
for _, user := range specs {
users = append(users, user.User.Username)
}
return users
}

// Checks that dynamic privileges are only of global scope.
Expand Down
Loading