1. Self-growth and lock
- Self-growth is a very common attribute in databases, and it is also the primary key method preferred by developers
Self-increasing counter
- In the memory structure of InnoDB, each table containing a value from the growth has a self-increment counter ( Auto-INCREMENT counter ), when the table containing the counter since the growth time of insertion operation, the counter is initialized
- Execute the following statement to get the value of the counter
select max(auto_inc_col) from t for update;
AUTO-INC Locking
- The insert operation will be assigned to the self-increasing column by adding 1 to the self-increasing counter value . This implementation is called AUTO-INC Locking
- This kind of lock actually uses a special table locking mechanism . In order to improve the performance of the insert, the lock is not released after a transaction is completed, but immediately after the SQL statement of the self-increasing value insertion is completed.
- Although AUTO-INC Locking improves the efficiency of concurrent inserts to a certain extent, there are still some performance problems :
- First of all, the performance of concurrent inserts for columns with self-increasing values is poor, and the transaction must wait for the completion of the previous insert (although there is no need to wait for the completion of the transaction)
- Secondly, the insertion of a large amount of data for INSERT...SELECT will affect the performance of the insert , because the insert in another transaction will be blocked
innodb_autoinc_lock_mode parameter
- Starting from MySQL 5.1.22 , InnoDB provides a lightweight mutex auto-increment implementation mechanism , which greatly improves the performance of auto-increment value insertion
- And starting from this version, the InnoDB storage engine provides this parameter to control the self-growth mode . The default value of this parameter is 1
- Before introducing the implementation of self-growth , you need to classify the self-growth insertion types, as shown in the following table :
- There are 3 valid values (0 , 1 , 2) for this parameter , which are described as follows:
The difference between InnoDB and MyIASM
In addition, it should be noted that the implementation of self-growth in InnoDB is different from MyIASM. MyIASM is a table lock design , and self-growth does not need to consider concurrent inserts.
Therefore, under the replication architecture of using the InnoDB storage engine on the master and the MyIASM storage engine on the slave, users must consider these two situations
In addition, in InnoDB, the self-growing column must be an index, and it must be the first column of the index . If it is not the first column, MySQL will throw an exception, but the MyIASM storage engine does not have this restriction . As shown below
create table t( a int auto_increment, b int, key(b,a) )engine=InnoDB;
create table t2( a int auto_increment, b int, key(b,a) )engine=MyISAM;
Two, foreign keys and locks
- Foreign keys are mainly used for referential integrity constraint checking
- In InnoDB, for a foreign key column, if the column is not explicitly indexed, InnoDB will automatically add an index to it, because this can avoid locking -this is better than Oracle database, Oracle database will not automatically To add an index, the user must add it manually, which also leads to a possible deadlock in Oracle
How foreign keys and locks work
- For the insertion or update of foreign key values, you first need to query the records in the parent table , that is , the SELECT parent table
- But for the SELECT operation of the parent table, the consistent non-locking read method is not used , because this will cause data inconsistency. Therefore , the SELECT...LOCK IN SHARE MODE method is used at this time , that is, actively add one to the parent table S lock. If there is already an X lock on the parent table at this time, the operation on the child table will be blocked
Demo case
- Create a parent table parent, insert 3 records into it
create table parent( id int primary key ); insert into parent select 1; insert into parent select 2; insert into parent select 3; select * from parent;
- Create a child table child. The second field of the child table is a foreign key, which points to the id field of the parent table
create table child( child_id int primary key, parent_id int not null, foreign key(parent_id) references parent(id) ); insert into child select 1,1; select * from child;
- Now open session A, delete the record with id 3 in the parent table in session A (at this time add an X lock to the record with id 3 ), but the transaction is not committed:
begin; delete from parent where id=3;
- At this time, opening a session B, I want to insert a statement (plus S lock) to the child table in the session B , since the second field is a foreign key, then this statement will be blocked (because the parent is the id field of 3 X lock has been added), you can see from the picture that the insert statement is blocked
begin; insert into child select 2,3;
- Imagine something (just hypothetical, not true) : If you are using a consistent non-locking read, then Session B will read a record with id=3 in the parent table. There will be inconsistencies in the data in the parent and child tables
- Now query the Innodb_locks table in session C , you will see the following results :
select * from information_schema.innodb_locks\G
- After a while, we look at session B again , we can see that the time waiting for the lock has timed out, and the statement failed to insert.
- The whole process is shown in the figure below:
- Note : After our session A is submitted, the insert statement of session B will also fail, because session A has deleted the field with id 3 in the parent table, so the insertion of session B will fail, which guarantees the relationship between the parent and child tables Data integrity and consistency
The content is taken from "Mysql Technology Insider---InnoDB Storage Engine"