You should know MySQL locks

background

Lock the database is used to ensure data consistency and stability of a mechanism in the case of multi-threaded high-concurrency. The MySQL different underlying storage engine, the lock granularity and support of different mechanisms to achieve. MyISAM only supports table locks, InnoDB supports row and table locks. Currently MySQL default storage engine is InnoDB, here introduces the InnoDB locks.

InnoDB storage engine

Two advantages of using InnoDB: First, to support the transaction; the second is support for row lock.

MySQL transaction

In the case of high concurrency concurrent processing transactions will bring several issues

  1. Dirty read: refers to the process of the transaction A transaction in the transaction data B are not submitted to read. For example, in the example of the transfer: A small transaction opened a small B to turn 1000, when the transaction is committed not just small B said the money has been credited into account. This time a small B to see what the balance and found really credited into account (and then happily went to brush vibrato), this time A small roll back the transaction, the 1000 and engage in back. Small B brushing vibrato to go look at the balance and found that the money was gone.

  2. Non-repeatable read: refers to a data query multiple times during the execution of a transaction when the phenomenon of inconsistent results, due to the process of implementation has been modified this data in another transaction and commit transaction. For example: Transaction A first read Bob's age is 18 years old, where transaction B will Xiaoming age changed to 20 and submitted, this time Transaction A reads again Xiaoming age of 20 is found, this is the same data non-repeatable reads.

  3. Reading Magic: Magic reading usually refers to the operation after a batch of data is completed, there are other matters and insert data to meet the conditions of a phenomenon caused. A transaction database gender male status is changed to 1 indicates the wealthy, this time Transaction B and inserted in a state of 0 people money record, this time, then the user will see just modify the data: for example, We found that there is no line changes, which appeared in phantom reads. Magic Reading is often for the insert operation, dirty reads and non-repeatable read for the select operation.

Because of these questions bring high concurrent transactions, so we had a transaction isolation level

  • Read uncommitted (read uncommitted): the lowest level, in any case can not be guaranteed.

  • Read committed (Read Committed): can avoid dirty reads to occur.

  • Repeatable read (Repeatable Read): can prevent dirty reads, unrepeatable reads occurring.

  • The Serializable (serialization): can prevent dirty reads, non-repeatable read, phantom read occurs.

InnoDB several common locking mechanism

  1. Shared and exclusive locks (Shared and Exclusive Locks), InnoDB implements standard row locks are exclusive locks and shared by two ways. Share locks (S locks): allows transactions to read data after acquiring the lock, exclusive lock (X lock): Allows a transaction to update or delete data after acquiring the lock. After a transaction acquires a shared lock S, allows other transactions acquire S lock, then two transactions are holding shared locks S, but get X lock does not allow other affairs. If a transaction acquires exclusive lock (X), it does not allow other transactions acquire S or X lock, the transaction must wait until the lock is released before they can get to. We can under the following SQL experience.

# T1
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT * FROM category WHERE category_no = 2 lock in SHARE mode; //共享锁
SELECT * FROM category WHERE category_no = 2 for UPDATE; //独占锁
COMMIT;
# T2
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT * FROM category WHERE category_no = 2 lock in SHARE mode; //共享锁
UPDATE category set category_name = '动漫' WHERE category_no = 2; //独占锁
COMMIT;
 

 

  1. Intent lock (Intention Locks), above said support InnoDB table locks and row locks, intent lock is a table lock, used to indicate the next transaction to be acquired what type of lock (shared or exclusive). Intent locks into intent shared lock (IS) and intent exclusive locks (IX), followed in turn represents a transaction will acquire a shared lock or exclusive lock. Intent locks do not need to display the acquisition, we will automatically get acquire a shared lock or an exclusive lock when the meaning is to say, if you want to acquire a shared lock or exclusive lock, it must first acquire a shared lock to the intent or intent exclusive lock . Intent locks do not lock anything unless there is operating a full table requests, it would not lock any data. The meaning of existence is only used to indicate there is a transaction locks a row of data, or about to lock a row of data.

    原文:Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table.

  2. Record lock (record Locks), to lock a row, if the table has index record locks are locks on the index, if the table has no indexes, then InnoDB creates a hidden clustered index lock. So when we try to use the index during query query, which can reduce lock conflicts.

  3. 间隙锁(Gap Locks),间隙锁是一种记录行与记录行之间存在空隙或在第一行记录之前或最后一行记录之后产生的锁。间隙锁可能占据的单行,多行或者是空记录。通常的情况是我们采用范围查找的时候,比如在学生成绩管理系统中,如果此时有学生成绩 60,72,80,95,一个老师要查下成绩大于 72 的所有同学的信息,采用的语句是 select * from student where grade > 72 for update,这个时候 InnoDB 锁住的不仅是 80,95,而是所有在 72-80,80-95,以及 95 以上的所有记录。为什么会 这样呢?实际上是因为如果不锁住这些行,那么如果另一个事务在此时插入了一条分数大于 72 的记录,那会导致第一次的事务两次查询的结果不一样,出现了幻读。所以为了在满足事务隔离级别的情况下需要锁住所有满足条件的行。

  4. Next-Key Locks,NK 是一种记录锁和间隙锁的组合锁。是 2 和 3 的组合形式,既锁住行也锁住间隙。并且采用的左开右闭的原则。InnoDB 对于查询都是采用这种锁的。

     

举个例子

 
 
CREATE TABLE `a` (  
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`uid` int(10) unsigned DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `idx_uid` (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `a`(uid) VALUES (1);
INSERT INTO `a`(uid) VALUES (2);
INSERT INTO `a`(uid) VALUES (3);
INSERT INTO `a`(uid) VALUES (6);
INSERT INTO `a`(uid) VALUES (10);

# T1START TRANSACTION WITH CONSISTENT SNAPSHOT; //1
SELECT * FROM a WHERE uid = 6 for UPDATE; //2
COMMIT; //5

# T2START TRANSACTION WITH CONSISTENT SNAPSHOT; //3
INSERT INto a(uid) VALUES(11);
INSERT INto a(uid) VALUES(5);

//4
INSERT INto a(uid) VALUES(7);
INSERT INto a(uid) VALUES(8);
INSERT INto a(uid) VALUES(9);
SELECT * FROM a WHERE uid = 6 for UPDATE;
COMMIT;
ROLLBACK;
 
 

 


 

按照上面 1,2,3,4 的顺序执行会发现第 4 步被阻塞了,必须执行完第 5 步后才能插入成功。这里我们会很奇怪明明锁住的是uid=6 的这一行,为什么不能插入 5 呢?原因就是这里采用了 next-key 的算法,锁住的是(3,10)整个区间。感兴趣的可以试一下。

Guess you like

Origin www.cnblogs.com/pypua/p/11130506.html