In-depth research on MySQL row locks

Source: Internet
Author: User

The following articles mainly introduce you to the in-depth study of MySQL row locks. Today, when we were working on a project, due to the needs of business logic, we should add MySQL row locks to one or more rows of a data table. The simplest example is the book lending system. Assume that the inventory of this book with id = 1 is 1, but two people borrow this book at the same time. The logic here is,

 
 
  1. view plaincopy to clipboardprint?  
  2. Select restnum from book where id =1 ;   

If the value of restnum is greater than 0, update

 
 
  1. Update book set restnumrestnum=restnum-1 where id=1 ;  

The problem arises. When two people borrow the data at the same time, it is possible that the first person executes the select statement and the second person inserts the data. When the first person does not have time to update the book table, the second person found the data, which is actually dirty data, because the first person will reduce the restnum value by 1, so the second person should have found that the restnum value of id = 1 is 0, therefore, the database will not execute update, but will tell it that the book with id = 1 is out of stock, but the database will only execute one SQL statement, no matter whether other SQL statements are inserted in the middle, it does not know whether to execute the SQL statement of one session before executing the SQL statement of another session.

Therefore, the final result of restnum during concurrency is-1, which is obviously unreasonable. Therefore, the concept of lock appears, mysql row locks use the innodb engine to lock data rows through indexes. The above borrow statement becomes:

 
 
  1. view plaincopy to clipboardprint?  
  2. Begin;   
  3. Select restnum from book where id =1 for update ;   

Apply an exclusive lock to the row with id = 1 and the id has an index.

 
 
  1. Update book set restnumrestnum=restnum-1 where id=1 ;   
  2. Commit;  

In this way, the second person will wait until the first person executes the commit statement. This ensures that the second person does not read the data before the modification of the first person.

Is this safe? The answer is no. Let's look at the example below.

Follow me step by step to create a table first

 
 
  1. view plaincopy to clipboardprint?  
  2. CREATE TABLE `book` (   
  3. `id` int(11) NOT NULL auto_increment,   
  4. `num` int(11) default NULL,   
  5. `name` varchar(0) default NULL,   
  6. PRIMARY KEY (`id`),   
  7. KEY `asd` (`num`)   
  8. ) ENGINE=InnoDB DEFAULT CHARSET=gbk   

The num field is indexed.

Then insert data and run,

 
 
  1. view plaincopy to clipboardprint?  
  2. insert into book(num) values(11),(11),(11),(11),(11);   
  3. insert into book(num) values(22),(22),(22),(22),(22);   

Then open two mysql row lock console windows, which is actually to create two sessions for concurrent operations.

Run in the first session:

 
 
  1. begin;   
  2. select * from book where num=11 for update;  

Result:

 
 
  1. +----+-----+------+   
  2. | id | num | name |   
  3. +----+-----+------+   
  4. | 11 | 11 | NULL |   
  5. | 12 | 11 | NULL |   
  6. | 13 | 11 | NULL |   
  7. | 14 | 11 | NULL |   
  8. | 15 | 11 | NULL |   
  9. +----+-----+------+   
  10. 5 rows in set  

Then run in the second session:

 
 
  1. begin;   
  2. select * from book where num=22 for update;  

Result:

 
 
  1. +----+-----+------+   
  2. | id | num | name |   
  3. +----+-----+------+   
  4. | 16 | 22 | NULL |   
  5. | 17 | 22 | NULL |   
  6. | 18 | 22 | NULL |   
  7. | 19 | 22 | NULL |   
  8. | 20 | 22 | NULL |   
  9. +----+-----+------+   
  10. 5 rows in set  

Okay, there are no problems here, right, but the problem is coming. Please refer:

Return to the first session and run:

 
 
  1. update book set name='abc' where num=11;  

The problem is that the session is in the waiting state, but isn't the row num = 11 locked by the first session itself? Why can't it be updated? Okay. You may have your own answer here. Don't worry. Please take a look at the operation.

Close both sessions and run:

 
 
  1. view plaincopy to clipboardprint?  
  2. delete from book where num=11 limit 3;   
  3. delete from book where num=22 limit 3;   

In fact, it is to delete three rows of records with num = 11 and 22 respectively,

Then, repeat the operations **********************.

It turns out that after you run update book set name = 'abc' where num = 11;, a result is displayed, indicating that it is not locked,

Why? Is there two rows of data and five rows of Data? For MySQL, there will be two cases: Lock row and lock table. After discussing with netizens and reading the materials, we found that:

When the above experimental data is used as the test data, because the repetition rate of the num field is too high, there are only two values, 11 and 12, respectively. the data size is relatively large compared with the two values, which is 10, 5 times the relationship.

Mysql ignores the index when interpreting the SQL statement, because its optimizer finds that even if an index is used, it still needs to perform a full table scan. Therefore, the index is discarded, no row lock is used, but table lock is used. To put it simply, MYSQL ignores your index. It feels that it is better to directly lock tables than to lock rows, after all, it thinks that table locks cost less than MySQL row locks. Even if you use force index to force the index, the results are the same and the table lock will always be applied.

Therefore, the row locks of mysql are not so free to use, and indexes must be considered. Let's look at the example below.

 
 
  1. view plaincopy to clipboardprint?  
  2. select id from items where id in (select id from items where id <6) for update;   
  3.  

-- The id field is indexed.

 
 
  1. select id from items where id in (1,2,3,4,5) for update;  

Most people will think that there is no difference between the same results. In fact, there is a big difference. The difference is that the first SQL statement will generate a table lock, and the second SQL statement is a MySQL row lock. Why? Because the first SQL statement uses the subquery peripheral query, the index is not used, resulting in the table lock.

Well, back to the example of borrowing books, because the id is unique, there is no problem, but if some tables have duplicate indexes, and mysql will force the use of table locks, what should we do? Generally, you only need to redesign the table structure and use new SQL statements to implement the business logic. However, there is still a way to use the above example. See the following code:

 
 
  1. View plaincopy to clipboardprint?
  2. Set SQL _mode =
  3. 'Strict _ TRANS_TABLES, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION ';
  4. Begin;
  5. Select restnum from book where id = 1; -- cancel the exclusive lock and set restnum to unsigned
  6. Update book set restnumrestnumnum = restnum-1 where id = 1;
  7. If (update execution successful) commit;
  8. Else rollback;

The above is a tip. By temporarily setting the database mode to the strict mode, when restnum is updated to-1, the update will fail because restnum is of the unsigned type, no matter what database operations the second session performs, it will be rolled back to ensure data correctness, this is only intended to prevent dirty Data Reading caused by nested SQL statements of two sessions with a low probability of concurrency.

Of course, the best way is to modify the table structure and SQL statements so that MYSQL can apply MySQL row locks through indexes. MySQL test versions are 5.0.75-log and 5.1.36-community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.