MySQL advanced knowledge and Optimization (VI): Mysql lock problem

Mysql lock problem

1 Lock Overview

Computer lock mechanism to coordinate multiple processes or threads concurrent access to a resource (to avoid competition).

In the database, in addition to traditional computing resources (such as CPU, RAM, I / O, etc.) than contention, the data is also a shared resource for many users. How to ensure the consistency of concurrent data access, availability is a problem that must be solved for all database lock conflicts is an important factor affecting the performance of concurrent access to the database. From this perspective, the lock is especially important for databases, but also more complicated.

Lock Category 2

From the size of the data operations points:

1) Table lock: When operating, it will lock the entire table.

2) Line lock: operation, operation will lock the current row.

From the type of data operation point:

1) read lock (shared locks): for the same data, multiple read operations can be carried out without affecting each other at the same time.

2) write lock (exclusive lock): Before the current operation is not completed, it will block other write locks and read locks.

3 Mysql lock

In contrast to other databases, MySQL locking mechanism is relatively simple, its most notable feature is the different storage engines support different lock mechanisms. The following table lists the supported Romania situation of each storage engine locks:

Storage Engine Table-level locking Row-level locking Page lock
MyISAM stand by not support not support
InnoDB stand by stand by not support
MEMORY stand by not support not support
BDB stand by not support stand by

MySQL lock these three characteristics may be roughly summarized as follows:

Lock Type Feature
Table-level locking Bias MyISAM storage engine, the overhead is small, locked fast; not deadlock; lock large size, the probability of lock conflicts of the highest and lowest degree of concurrency.
Row-level locking Bias InnoDB storage engine, large overhead, locking slow; there will be a deadlock; locking granularity smallest and lowest probability of lock conflicts, have the highest degree of concurrency.
Page lock Locking overhead and time boundaries between the table and row locks; deadlock occurs; boundary between the lock granularity and row locks the table, the general concurrency.

From the above features, it is difficult to say in general terms what better lock, features only on specific applications for which the lock is more appropriate! Only from the perspective of the lock: table lock is more adapted to query-based, only a few are applied in the condition updating the index data, such as Web applications; and row-level locks are more suitable for a large number of concurrent update conditions by the small number of different index data, applications, and while there are queries, such as some online transaction processing (OLTP) systems.

2 MyISAM table locks

MyISAM storage engine only supports table locks, which is the start of several types of locks MySQL versions only supported.

2.1 How to add table lock

MyISAM before executing the query (SELECT), will be automatically added to all table read locks involved, before performing the update operation (UPDATE, DELETE, INSERT, etc.), will be automatically added to the table write locks involved, this process does not require user intervention, thus users generally do not need to directly MyISAM table with explicit lock command lOCK tABLE.

Table lock display plus syntax:

加读锁 : lock table table_name read;

加写锁 : lock table table_name write;
2.2 read lock case

Preparing the environment

create database demo_03 default charset=utf8mb4;

use demo_03;

CREATE TABLE `tb_book` (
  `id` INT(11) auto_increment,
  `name` VARCHAR(50) DEFAULT NULL,
  `publish_time` DATE DEFAULT NULL,
  `status` CHAR(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;

INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'java编程思想','2088-08-01','1');
INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'solr编程思想','2088-08-08','0');



CREATE TABLE `tb_user` (
  `id` INT(11) auto_increment,
  `name` VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;

INSERT INTO tb_user (id, name) VALUES(NULL,'令狐冲');
INSERT INTO tb_user (id, name) VALUES(NULL,'田伯光');

A client:

1) to obtain a read lock tb_book table

lock table tb_book read;

2) execute the query operation

select * from tb_book;

Here Insert Picture Description

Can perform normal, check out the data.

Client II:

3) execute the query operation

select * from tb_book;

Here Insert Picture Description

A client:

4) Query unlocked table

select name from tb_seller;

Here Insert Picture Description

Client II:

5) unlocked query tables

select name from tb_seller;

Here Insert Picture Description

You can check out the unlocked normal table;

A client:

6) insertion operation

insert into tb_book values(null,'Mysql高级','2088-01-01','1');

Here Insert Picture Description

Insertion, given directly, because the current is obtained tb_book read lock, can not perform the update operation.

Client II:

7) insert operation

insert into tb_book values(null,'Mysql高级','2088-01-01','1');

Here Insert Picture Description

When the unlock tables in the client in a lock release instruction, the client inesrt two statements immediately executed;

2.3 Write Lock Case

A client:

1) to obtain a write lock tb_book table

lock table tb_book write ;

2) execute the query operation

select * from tb_book ;

Here Insert Picture Description

Query operations successfully;

3) update operation

update tb_book set name = 'java编程思想(第二版)' where id = 1;

Here Insert Picture Description

Update successfully executed;

Client II:

4) execute the query operation

select * from tb_book ;

Here Insert Picture Description

When the unlock tables in the client in a lock release instruction, the client II select statement is executed immediately;

Here Insert Picture Description

2.4 Conclusion

Mutual compatibility lock mode as shown in the table:

Here Insert Picture Description
Above table shows:

1) to read MyISAM table, without blocking other users on the same table read requests, but will block the request to write the same table;

2) to write MyISAM table, it will block other users on the same table read and write operations;

In short, read lock will block write, but will not block reading. The write lock, you can block both read and write will clog.

In addition, MyISAM read-write locks scheduling priority is to write, this is MyISAM reason not suitable for write-based storage engine tables. Because the write lock, other threads can not do anything, make a lot of update queries is difficult to get a lock, resulting in block forever.

2.5 View contention for locks
show open tables;

Here Insert Picture Description

In_user: table number currently being used by the query. If the number is zero, the table is open, but not currently being used.

Name_locked: table name is locked. Locking the table name or table for canceling rename operation.

show status like 'Table_locks%';

Here Insert Picture Description
Table_locks_immediate : 指的是能够立即获得表级锁的次数,每立即获取锁,值加1。

Table_locks_waited : 指的是不能立即获取表级锁而需要等待的次数,每等待一次,该值加1,此值高说明存在着较为严重的表级锁争用情况。

3 InnoDB 行锁

3.1 行锁介绍

行锁特点 :偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

InnoDB 与 MyISAM 的最大不同有两点:一是支持事务;二是 采用了行级锁。

3.2 背景知识

事务及其ACID属性

事务是由一组SQL语句组成的逻辑处理单元。

事务具有以下4个特性,简称为事务ACID属性。

ACID属性 含义
原子性(Atomicity) 事务是一个原子操作单元,其对数据的修改,要么全部成功,要么全部失败。
一致性(Consistent) 在事务开始和完成时,数据都必须保持一致状态。
隔离性(Isolation) 数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的 “独立” 环境下运行。
持久性(Durable) 事务完成之后,对于数据的修改是永久的。

并发事务处理带来的问题

问题 含义
丢失更新(Lost Update) 当两个或多个事务选择同一行,最初的事务修改的值,会被后面的事务修改的值覆盖。
脏读(Dirty Reads) 当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
不可重复读(Non-Repeatable Reads) 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现和以前读出的数据不一致。
幻读(Phantom Reads) 一个事务按照相同的查询条件重新读取以前查询过的数据,却发现其他事务插入了满足其查询条件的新数据。

事务隔离级别

为了解决上述提到的事务并发问题,数据库提供一定的事务隔离机制来解决这个问题。数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使用事务在一定程度上“串行化” 进行,这显然与“并发” 是矛盾的。

数据库的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏写、脏读、不可重复读、幻读这几类问题。

隔离级别 丢失更新 脏读 不可重复读 幻读
Read uncommitted ×
Read committed × ×
Repeatable read(默认) × × ×
Serializable × × × ×

备注 : √ 代表可能出现 , × 代表不会出现 。

Mysql 的数据库的默认隔离级别为 Repeatable read , 查看方式:

show variables like 'tx_isolation';

Here Insert Picture Description

3.3 InnoDB 的行锁模式

InnoDB 实现了以下两种类型的行锁。

  • 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);

对于普通SELECT语句,InnoDB不会加任何锁;

可以通过以下语句显示给记录集加共享锁或排他锁 。

共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE
3.4 案例准备工作
create table test_innodb_lock(
	id int(11),
	name varchar(16),
	sex varchar(1)
)engine = innodb default charset=utf8;

insert into test_innodb_lock values(1,'100','1');
insert into test_innodb_lock values(3,'3','1');
insert into test_innodb_lock values(4,'400','0');
insert into test_innodb_lock values(5,'500','1');
insert into test_innodb_lock values(6,'600','0');
insert into test_innodb_lock values(7,'700','0');
insert into test_innodb_lock values(8,'800','1');
insert into test_innodb_lock values(9,'900','1');
insert into test_innodb_lock values(1,'200','0');

create index idx_test_innodb_lock_id on test_innodb_lock(id);
create index idx_test_innodb_lock_name on test_innodb_lock(name);
3.5 行锁基本演示
Session-1 Session-2
Here Insert Picture Description 关闭自动提交功能 Here Insert Picture Description 关闭自动提交功能
Here Insert Picture Description 可以正常的查询出全部的数据 Here Insert Picture Description 可以正常的查询出全部的数据
Here Insert Picture Description查询id 为3的数据 ; Here Insert Picture Description获取id为3的数据 ;
Here Insert Picture Description 更新id为3的数据,但是不提交; Here Insert Picture Description 更新id为3 的数据, 出于等待状态
Here Insert Picture Description 通过commit, 提交事务 ] 解除阻塞,更新正常进行
以上, 操作的都是同一行的数据,接下来,演示不同行的数据 :
Here Insert Picture Description 更新id为3数据,正常的获取到行锁 , 执行更新 ; Here Insert Picture Description 由于与Session-1 操作不是同一行,获取当前行锁,执行更新;
3.6 无索引行锁升级为表锁

如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样。

查看当前表的索引 : show index from test_innodb_lock ;

Here Insert Picture Description

Session-1 Session-2
关闭事务的自动提交Here Insert Picture Description 关闭事务的自动提交Here Insert Picture Description
执行更新语句 :Here Insert Picture Description 执行更新语句, 但处于阻塞状态:Here Insert Picture Description
提交事务:Here Insert Picture Description 解除阻塞,执行更新成功 :Here Insert Picture Description
执行提交操作 :[Image dump the chain fails, the source station may have security chain mechanism, it is recommended to save the picture down uploaded directly (img-vrZN11qd-1577190424060) (assets / 1554386804807.png)]

由于 执行更新时 , name字段本来为varchar类型, 我们是作为数组类型使用,存在类型转换,索引失效,最终行锁变为表锁 ;

3.7 间隙锁危害

当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁; 对于键值在条件范围内但并不存在的记录,叫做 “间隙(GAP)” , InnoDB也会对这个 “间隙” 加锁,这种锁机制就是所谓的 间隙锁(Next-Key锁) 。

示例 :

Session-1 Session-2
关闭事务自动提交Here Insert Picture Description 关闭事务自动提交Here Insert Picture Description
根据id范围更新数据Here Insert Picture Description
插入id为2的记录, 出于阻塞状态Here Insert Picture Description
提交事务 ;Here Insert Picture Description
解除阻塞 , 执行插入操作 :Here Insert Picture Description
提交事务 :
3.8 InnoDB 行锁争用情况
show  status like 'innodb_row_lock%';

Here Insert Picture Description

Innodb_row_lock_current_waits: 当前正在等待锁定的数量

Innodb_row_lock_time: 从系统启动到现在锁定总时间长度

Innodb_row_lock_time_avg:每次等待所花平均时长

Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间

Innodb_row_lock_waits: 系统启动后到现在总共等待的次数


当等待的次数很高,而且每次等待的时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化计划。

3.9 总结

InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些,但是在整体并发处理能力方面要远远由于MyISAM的表锁的。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势。

但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能会更差。

Published 109 original articles · won praise 47 · views 30000 +

Guess you like

Origin blog.csdn.net/weixin_43934607/article/details/103689319
Recommended