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

Merged
merged 61 commits into from
Jun 18, 2019
Merged

Conversation

crazycs520
Copy link
Contributor

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

@crazycs520 crazycs520 added type/new-feature require-LGT3 Indicates that the PR requires three LGTM. labels May 5, 2019
@codecov
Copy link

codecov bot commented May 5, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@04cd877). Click here to learn what that means.
The diff coverage is 81.1828%.

@@             Coverage Diff             @@
##             master     #10343   +/-   ##
===========================================
  Coverage          ?   80.8257%           
===========================================
  Files             ?        419           
  Lines             ?      88546           
  Branches          ?          0           
===========================================
  Hits              ?      71568           
  Misses            ?      11753           
  Partials          ?       5225

@crazycs520 crazycs520 requested a review from zimulala May 5, 2019 07:41
@crazycs520
Copy link
Contributor Author

/run-all-tests

lock/lock.go Show resolved Hide resolved
zimulala
zimulala previously approved these changes Jun 18, 2019
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 status/LGT3 The PR has already had 3 LGTM. and removed status/LGT2 Indicates that a PR has LGTM 2. labels Jun 18, 2019
@zimulala
Copy link
Contributor

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-all-tests

1 similar comment
@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520 crazycs520 merged commit 612936b into pingcap:master Jun 18, 2019
marsishandsome pushed a commit to marsishandsome/tidb that referenced this pull request Jul 24, 2019
lzmhhh123 pushed a commit to lzmhhh123/tidb that referenced this pull request Jan 19, 2020
crazycs520 added a commit to crazycs520/tidb that referenced this pull request Apr 23, 2020
@bb7133 bb7133 mentioned this pull request Aug 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
require-LGT3 Indicates that the PR requires three LGTM. status/LGT3 The PR has already had 3 LGTM. type/new-feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants