Skip to content
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

*: try to support lock/unlock tables function #305

Merged
merged 19 commits into from
Jun 10, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
62 changes: 62 additions & 0 deletions ast/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,68 @@ func (n *DropIndexStmt) Accept(v Visitor) (Node, bool) {
return v.Leave(n)
}

// LockTablesStmt is a statement to lock tables.
type LockTablesStmt struct {
ddlNode

TableLocks []TableLock
}

// TableLock contains the table name and lock type.
type TableLock struct {
Table *TableName
Type model.TableLockType
}

// Accept implements Node Accept interface.
func (n *LockTablesStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*LockTablesStmt)
for i := range n.TableLocks {
node, ok := n.TableLocks[i].Table.Accept(v)
if !ok {
return n, false
}
n.TableLocks[i].Table = node.(*TableName)
}
return v.Leave(n)
}

// Restore implements Node interface.
func (n *LockTablesStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("LOCK TABLES ")
for i, tl := range n.TableLocks {
if i != 0 {
ctx.WritePlain(", ")
}
if err := tl.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while add index")
}
ctx.WriteKeyWord(" " + tl.Type.String())
}
return nil
}

// UnlockTablesStmt is a statement to unlock tables.
type UnlockTablesStmt struct {
ddlNode
}

// Accept implements Node Accept interface.
func (n *UnlockTablesStmt) Accept(v Visitor) (Node, bool) {
_, _ = v.Enter(n)
return v.Leave(n)
}

// Restore implements Node interface.
func (n *UnlockTablesStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("UNLOCK TABLES")
return nil
}

// TableOptionType is the type for TableOption
type TableOptionType int

Expand Down
4 changes: 4 additions & 0 deletions model/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const (
ActionTruncateTablePartition ActionType = 23
ActionDropView ActionType = 24
ActionRecoverTable ActionType = 25
ActionLockTable ActionType = 26
ActionUnlockTable ActionType = 27
)

// AddIndexStr is a string related to the operation of "add index".
Expand Down Expand Up @@ -86,6 +88,8 @@ var actionMap = map[ActionType]string{
ActionTruncateTablePartition: "truncate partition",
ActionDropView: "drop view",
ActionRecoverTable: "recover table",
ActionLockTable: "lock table",
ActionUnlockTable: "unlock table",
}

// String return current ddl action in string
Expand Down
91 changes: 91 additions & 0 deletions model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package model

import (
"encoding/json"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -230,11 +231,101 @@ type TableInfo struct {
Compression string `json:"compression"`

View *ViewInfo `json:"view"`
// Lock represent the table lock info.
Lock *TableLockInfo `json:"Lock"`

// Version means the version of the table info.
Version uint16 `json:"version"`
}

// TableLockInfo provides meta data describing a table lock.
type TableLockInfo struct {
Tp TableLockType
// Use array because there maybe multiple session both hold same read lock.
crazycs520 marked this conversation as resolved.
Show resolved Hide resolved
Sessions []SessionInfo
State TableLockState
// TS use to record the timestamp of this table lock been public locked.
crazycs520 marked this conversation as resolved.
Show resolved Hide resolved
TS uint64
}

// SessionInfo contain the session ID and the server ID.
type SessionInfo struct {
ServerID string
SessionID uint64
}

func (s SessionInfo) String() string {
return "server:" + s.ServerID + "_session:" + strconv.FormatUint(s.SessionID, 10)
crazycs520 marked this conversation as resolved.
Show resolved Hide resolved
}

// DBTableID is composed by schema ID and table ID.
type DBTableID struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks that this is not used anymore, right?

DBID int64
TableID int64
}

// TableLockTpInfo is composed by schema ID, table ID and table lock type.
type TableLockTpInfo struct {
SchemaID int64
TableID int64
Tp TableLockType
}

// TableLockState is the state for table lock.
type TableLockState byte

const (
// TableLockStateNone means this table lock is absent.
TableLockStateNone TableLockState = iota
// TableLockStatePreLock means this table lock is pre-lock state. Other session doesn't hold this lock should't do corresponding operation according to the lock type.
TableLockStatePreLock
// TableLockStatePublic means this table lock is public state.
TableLockStatePublic
)

// String implements fmt.Stringer interface.
func (t TableLockState) String() string {
switch t {
case TableLockStatePreLock:
return "pre-lock"
case TableLockStatePublic:
return "public"
default:
return "none"
}
}

// TableLockType is the type of the table lock.
type TableLockType byte

const (
TableLockNone TableLockType = iota
// TableLockRead means the session with this lock has read permission, other session can't read/write until the lock is released.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO we need to add more detailed explanations. For example, if the locks are exclusive, or can be shared.

Although the behavior of LOCKS will be explained in our official document, detailed comments are still useful here for the developers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked the implementations, this comment is wrong(other session can't read/write ...), please fix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for my mistakes, PTAL again.

TableLockRead
// TableLockReadLocal is not supported. TableLockReadLocal enables nonconflicting INSERT statements by other sessions to execute while the lock is held.
TableLockReadLocal
// TableLockWrite means only the session with this lock has write/read permission, other session can't read/write until the lock is released.
TableLockWrite
// TableLockWriteLocal means the session with this lock has write/read permission, and the other session is still has read permission.
crazycs520 marked this conversation as resolved.
Show resolved Hide resolved
TableLockWriteLocal
)

func (t TableLockType) String() string {
switch t {
case TableLockNone:
return "NONE"
case TableLockRead:
return "READ"
case TableLockReadLocal:
return "READ LOCAL"
case TableLockWriteLocal:
return "WRITE LOCAL"
case TableLockWrite:
return "WRITE"
}
return ""
}

// GetPartitionInfo returns the partition information.
func (t *TableInfo) GetPartitionInfo() *PartitionInfo {
if t.Partition != nil && t.Partition.Enable {
Expand Down
Loading