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

*: Support LOCK/UNLOCK TABLES feature (#10343) #16772

Merged
merged 4 commits into from
Apr 27, 2020

Conversation

crazycs520
Copy link
Contributor

@crazycs520 crazycs520 commented Apr 23, 2020

What problem does this PR solve?

cherry-pick #10343

conflict file

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

        both modified:   config/config.go
        both modified:   config/config.toml.example
        both modified:   config/config_test.go
        both modified:   ddl/ddl_api.go
        both modified:   sessionctx/context.go

What problem does this PR solve?

Background

Currently, we only support LOCK TABLES/UNLOCK TABLES syntax, but actually do nothing.

TiDB only supports Optimistic Lock currently. A large write transaction maybe failed caused by other transaction has 1 insert. Large transaction retries are expensive, so we want to use LOCK TABLES to avoid this expensive retry.

Proposal

LOCK TABLES explicitly acquires table locks for the current client session. Table locks can be only acquired for base tables, not support for views. You must have the LOCK TABLES privilege, and the SELECT privilege for each table to be locked.

UNLOCK TABLES explicitly releases any table locks held by the current session.

LOCK TABLES implicitly releases any table locks held by the current session before acquiring new locks.

While the locks thus obtained are held, the session can access only the locked tables. Tables in the INFORMATION_SCHEMA database are an exception. They can be accessed without being locked explicitly.

tidb > LOCK TABLES t WRITE;
Query OK, 0 rows affected (0.00 sec)
tidb > SELECT COUNT(*) FROM t1;
ERROR 1100 (HY000): Table 't1' was not locked with LOCK TABLES
tidb > select * from INFORMATION_SCHEMA.VIEWS;
Empty set (0.00 sec)

LOCK TABLES or UNLOCK TABLES, when applied to a partitioned table, always locks or unlocks the entire table; these statements do not support partition lock pruning.

Principles

  1. If a session issues a LOCK TABLES statement to acquire a lock while already holding locks, its existing locks are released implicitly before the new locks are granted.
  2. If a session begins a transaction (for example, with START TRANSACTION), an implicit UNLOCK TABLES is performed, which causes existing locks to be released. (not implement currently)

The Difference with Mysql LOCK TABLE

  1. You can't implement transaction with LOCK TABLES and UNLOCK TABLES in TiDB. If you need transaction, you should also execute begin after LOCK TABLES.

    Table locks of mysql is metadata locks, and user can use table locks to implement transaction when the mysql storage engine is nontransactional.

    Because MySQL execute select/insert/update will automatically to acquire the related table locks first. If session 1 is executing a select * from t1, and session 2 execute lock tables t1 write, then session 2 won't aquire the t1 table lock untill the session 1 execute finish. Details as follows chart:

Time Session 1( In MySQL) Session 2 ( In MySQL)
t1 Select * from t1
t2 Acquire t1 table lock.
t3 doing Lock tables t1 write
t4 doing waiting
t5 (Select * from t1) Finish waiting
t6 Release t1 table lock. waiting
t7 (Lock tables t1 write ) sucess.

But in TiDB, session2 will aquire the t1 table lock soon. Because session 1 won't acquire the t1 table lock. In TiDB, It is very expensive to acquire the related table locks when execute DML like select/insert. Details in TiDB as follows chart:

Time Session 1( In TiDB) Session 2 ( In TiDB)
t1 Select * from t1
t2 doing Lock tables t1 write
t3 doing (Lock tables t1 write ) sucess.
t4 (Select * from t1) Finish
  1. MySQL session1 execute LOCK TABLES t1 write, if other session2 obtains the lock of t1, session 1 will wait until the session2 release t1 lock. In TiDB, session 1 will return error like: Table 't1' was locked by server xx session xx.

    Time Session 1 session 2 In MySQL Session 2 in TiDB
    t1 Lock tables t1 read
    t2 Lock tables t1 write Lock tables t1 write
    t3 wait Error: Table 't1' was locked by server xx session 1
    t4 Unlock tables. wait
    t5 Lock tables t1 write sucess.
  2. TiDB table lock not support alias name currently. TiDB will lock the table.ID instead of table.Name

What is changed and how it works?

  1. Store TableLockInfo in TableInfo.
  2. Use DDL to implement LOCK TABLES and UNLOCK TABLES. So add 2 DDL job type: ActionLockTable, ActionUnlockTable.
  3. Store lockedTables map in session. lockedTables use to record the table locks hold by the session.
  4. Check the table locked before execute. CheckTableLock will use the visitInfo to check table locked. This check was add after the CheckPrivilege.

Related parser PR: pingcap/parser#305

Check List

Tests

  • Unit test
  • Integration test( need more test, in doing )

Code changes

  • Has exported function/method change

Side effects

  • Possible performance regression

Release note

@crazycs520
Copy link
Contributor Author

/run-all-tests

@github-actions github-actions bot added component/config sig/sql-infra SIG: SQL Infra sig/execution SIG execution sig/planner SIG: Planner labels Apr 23, 2020
@crazycs520
Copy link
Contributor Author

/rebuild

@crazycs520
Copy link
Contributor Author

/build

@crazycs520
Copy link
Contributor Author

Ci will happy after the parser PR merged, pingcap/parser#827 @bb7133 PTAL

Copy link
Contributor

@zimulala zimulala left a comment

Choose a reason for hiding this comment

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

LGTM

@zimulala zimulala added the status/LGT1 Indicates that a PR has LGTM 1. label Apr 24, 2020
@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/rebuild

1 similar comment
@crazycs520
Copy link
Contributor Author

/rebuild

Copy link
Member

@bb7133 bb7133 left a comment

Choose a reason for hiding this comment

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

LGTM

@bb7133 bb7133 added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Apr 27, 2020
@bb7133
Copy link
Member

bb7133 commented Apr 27, 2020

/merge

@sre-bot sre-bot added the status/can-merge Indicates a PR has been approved by a committer. label Apr 27, 2020
@sre-bot
Copy link
Contributor

sre-bot commented Apr 27, 2020

/run-all-tests

@sre-bot sre-bot merged commit cd9e3bb into pingcap:release-3.0 Apr 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/config sig/execution SIG execution sig/planner SIG: Planner sig/sql-infra SIG: SQL Infra status/can-merge Indicates a PR has been approved by a committer. status/LGT2 Indicates that a PR has LGTM 2. type/3.0-cherry-pick
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants