热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mysql的锁定机制_MYSQL锁的机制详解

锁是计算机协调多个进程和线程并发访问某一资源的机制,在数据库中除了传统的计算机资源,CPU,内存,IO以外,数据也是一种供许多用户共享的资

锁是计算机协调多个进程和线程并发访问某一资源的机制,在数据库中除了传统的计算机资源,CPU,内存,IO以外,数据也是一种供许多用户共享的资源,如何保证数据并发访问的一致性、有效性是所有数据库必须要解决的问题,锁冲突也是影响数据库并发性能的一个重要参数。

OPTIMIZE TABLE 语句可以整理空间碎片,收回因为删除记录而产生的中间空洞。

一、分类

对InnoDB锁按颗粒度进行划分, 可分为表锁和行锁 :表锁:

• 意向锁(Intention Lock) 。

• 自增锁(AUTO-INC Lock) 。

行锁:

• 共享锁与排他锁(Shared and Exclusive Lock) 。

• 记录锁(Record Lock) 。

• 间隙锁(Gap Lock) 。

• 记录锁与间隙锁的组合(Next-Key Lock) 。

• 插入意向锁(Insert Intention Lock) 。

二、详解

1.行锁

1.1 .共享锁与排他锁

行共享锁(S) 与排他锁(X) 较好理解, S锁与X锁互相冲突。

• 当读取一行记录时, 为了防止别人修改, 则需要添加S锁。

• 当修改一行记录时, 为了防止别人同时进行修改, 则需要添加X锁。

这里需要知道MySQL具有MVCC特性, 所以, 在通常情况下, 普通的查询属于非锁定读, 不会添加任何锁(即一致性读) 。 还有一种是锁定读(即当前读);

例如:

• SELECT… FOR SHARE(MySQL 8.0中新增的方式, 在以前版本中上锁方式为 SELECT ... LOCK IN SHARE MODE), 添加S锁, 其他事务可以读但修改会被阻塞。

• SELECT… FOR UPDATE, 添加X锁, 其他事务修改或者执行SELECT … FOR SHARE都会被阻塞。1.2. 记录锁在MySQL中记录锁都是添加在索引上的, 即使表中没有索引,

也会在默认创建的聚集索引上添加记录锁。

1.3. 间隙锁间隙锁的锁定范围是索引记录之间的间隙, 或者第一条或最后一条索引记录之前的间隙, 间隙锁是针对事务隔离级别为可重复读或以上级别的。

例如一个事务执行SELECT *FROM t WHERE c1 > 10 AND c1 <20 FOR UPDATE ;&#xff0c; 那么当插入c1&#61;15时就会被阻塞&#xff1b;否则&#xff0c; 再次查询得到的结果就与第一次不一致。

1.4&#xff0e; 记录锁与间隙锁的组合Next-Key Lock是记录锁与间隙锁的组合&#xff0c; 也就是索引记录本身加上之前的间隙。 间隙锁保证在REPEATABLE-READ级别下不会出现幻读现象&#xff0c;

防止在同一个事务内得到的结果不一致。 间隙锁在执行show engine innodb 时输出结果如下( 后面会有详细解释) &#xff1a;

1.5&#xff0e; 插入意向锁插入意向锁是针对INSERT操作设置的一种特殊的间隙锁&#xff0c; 主要是为了优化INSERT操作的并发能力。 这个锁表示插入的意图&#xff0c; 即插入具有相同索引间隙的多个事务&#xff0c;

如果插入的值不同&#xff0c; 则不需要互相等待。假设存在值为4和7的索引记录&#xff0c; 现在分别尝试插入值为5和6的事务&#xff0c; 在获取插入行上的排他锁之前&#xff0c;

会添加插入意向锁锁定4和7之间的间隙&#xff0c; 但是不会互相阻塞&#xff0c; 因为插入的行是不冲突的。这里需要注意的是&#xff0c; 插入意向锁之间是不冲突的&#xff0c; 但是插入意向锁可能和其他锁是冲突的&#xff0c;

比如Next-Key Lock。查看行锁的竞争情况&#xff1a;

MariaDB [(none)]> show status like &#39;innodb_row_lock%&#39;;&#43;-------------------------------&#43;-------&#43;

| Variable_name | Value |

&#43;-------------------------------&#43;-------&#43;

| Innodb_row_lock_current_waits | 0 |

| Innodb_row_lock_time | 36922 |

| Innodb_row_lock_time_avg | 3 |

| Innodb_row_lock_time_max | 17 |

| Innodb_row_lock_waits | 11646 |

&#43;-------------------------------&#43;-------&#43;

5 rows in set (0.00 sec)

如果innodb_row_lock_waits 和innodb_lock_time_avg 的值较高&#xff0c;说明锁竞争比较严重。

可以通过如下命令查看锁情况&#xff1a;

select * from innodb_locks \G

也可以打开InnoDB Monitors 锁冲突的情况&#xff1a;

create table innodb_monitor(a int) engine&#61;innodb;

show engine innodb status \G;

注意&#xff1a;设置监视器以后&#xff0c;show engine innodb status可以查看到详细的锁信息&#xff0c;而且没15秒会向日志文件中记录监控内容&#xff0c;所以会使得日子文件变得非常大&#xff0c;要记得使用之后关闭监视器。

2.表锁(不会出现死锁)

MYSQL的MYISAM存储引擎只支持表锁&#xff0c;这也是mysql开始几个版本中唯一支持的锁类型&#xff0c;表锁依然是使用最为广泛的锁类型。

可以通过table_locks_waited 和table_locks_immediate状态变量来分析系统上的表锁定争夺。

mysql> show status like &#39;table%&#39;;&#43;----------------------------&#43;-------&#43;

| Variable_name | Value |

&#43;----------------------------&#43;-------&#43;

| Table_locks_immediate | 117 |

| Table_locks_waited | 0 |

| Table_open_cache_hits | 0 |

| Table_open_cache_misses | 0 |

| Table_open_cache_overflows | 0 |

&#43;----------------------------&#43;-------&#43;

如果Table_locks_waited的值比较大&#xff0c;那说明表的锁竞争比较严重。

表锁的锁模式&#xff1a;

ee3e54828a79589689d4fcb6b9886217.png

mysql的表锁有两种模式&#xff1a;表共享锁和表独占锁&#xff1b;

1. MYISAM对表的读操作&#xff0c;不会阻塞其他用户对同一表的读请求&#xff0c;但是会阻塞对同一表的写请求。

2. MYISAM对表的写操作&#xff0c;会阻塞其他用户对同一表的读写操作。

所以当一个线程获得对一个表的写锁之后&#xff0c;只有持有锁的线程可以对表进行更新操作&#xff0c;其他线程的读写操作都会等待&#xff0c;知道锁被释放。

加锁&#xff1a;

通常我们在查询或者修改记录时&#xff0c;mysql会自动加读锁或者写锁。

手动加锁&#xff1a;

lock tables table1 read local, table2 read local;

lock table table1 write;

unlock tables;

2.1 表锁之意向锁

意向锁在MySQL中是表级别锁&#xff0c; 表示将来要对表添加什么类型的锁( IX/IS) 。

• SELECT… FOR SHARE&#xff0c; 添加意向共享锁( IS) 。

• SELECT … FOR UPDATE&#xff0c; 添加意向排他锁( IX) 。

在获取表中某行的共享锁之前&#xff0c; 首先必须获取表的IS锁。 在获取表中某行的独占锁之前&#xff0c; 首先必须获取表的IX锁。 意向锁和行锁之间的冲突及兼容列表如表20-1所示。

4a2a22139d86d09ba82b8c140845dd14.png

意向锁不会阻止除表锁请求(例如&#xff0c; 执行LOCK table … WRITE语句) 之外的锁。 可以这样理解&#xff1a; 在申请表锁(执行LOCK table语句) 时表记录不能存在锁&#xff0c;

在没有意向锁的情况下&#xff0c; 就需要扫描表中每一条记录&#xff0c; 查看记录上是否存在锁&#xff1b; 但是有了意向锁之后&#xff0c; 只要判断表上是否存在意向锁即可&#xff0c; 如果有意向锁存在&#xff0c;

则说明表中某行记录已被锁定或者将要被锁定&#xff0c; 表锁的申请语句(LOCK table) 会等待&#xff0c; 意向锁设计提高了效率。

2.2表锁之自增锁

2&#xff0e; 自增锁

自增锁是插入到具有AUTO_INCREMENT字段的表中的事务所采用的特殊表级锁。

在最简单的情况下&#xff0c; 如果一个事务正在向表中插入值&#xff0c; 则其他任何事务都必须等待插入语

句执行完成&#xff0c; 这样才能保证后面事务插入的主键值是连续的。

innodb_autoinc_lock_mode参数用于控制自增锁的算法&#xff0c; 通过控制自增值生成的策略

来提高并发能力

三、锁模式对应的含义

当我们使用show engine innodb语句查看锁信息时&#xff0c; 经常会看到LOCK_MODE字段&#xff0c;也就是锁模式&#xff0c; 只有知道各种模式都分别代表什么意思才能更好地去分析锁等待和死锁问题。 这是一个非常重要的知识点。

• IX&#xff1a; 代表意向排他锁。

• X&#xff1a; 代表Next-Key Lock锁定记录本身和记录之前的间隙(X) 。

• S&#xff1a; 代表Next-Key Lock锁定记录本身和记录之前的间隙(S) 。

• X, REC_NOT_GAP&#xff1a; 代表只锁定记录本身(X) 。

• S, REC_NOT_GAP&#xff1a; 代表只锁定记录本身(S) 。

• X, GAP&#xff1a; 代表间隙锁&#xff0c; 不锁定记录本身(X) 。

• S, GAP&#xff1a; 代表间隙锁&#xff0c; 不锁定记录本身(S) 。

• X, GAP,INSERT_INTENTION&#xff1a; 代表插入意向锁。

相比其他其他数据库而言&#xff0c;mysql的锁的机制比较简单&#xff0c;最显著的特点是不同的存储引擎支持的锁的机制不同&#xff0c;比如MYIASM和MEMORY存储引擎采用的是表级锁&#xff0c;

BDB存储引擎采用的是页面锁&#xff0c;但是也支持表级锁&#xff0c;innoDB默认使用行级锁&#xff0c;但是也支持表级锁。

MYSQL三种锁的特性可以大致归纳纳入下&#xff1a;

表级锁&#xff1a;开销小&#xff0c;加锁快&#xff0c;不会出现死锁&#xff0c;锁定的粒度大&#xff0c;但是发生锁的冲突的概率最高&#xff0c;并行度最低。

行级锁&#xff1a;开销大&#xff0c;加锁慢&#xff0c;会出现死锁&#xff0c;锁定粒度最小&#xff0c;但是但是发生锁的冲突的概率最低&#xff0c;并行度最高。

页面锁&#xff1a;开销和加锁速度介于表锁和行锁之间&#xff0c;会出现死锁&#xff0c;锁定粒度和并发度介于两者之间。

由此可以看出表锁更加适合已查询为主&#xff0c;只有少量按索引条件更新数据的应用&#xff0c;如web应用。

行锁更加适合有大量按照索引条件并发更新少量不同的数据&#xff0c;同时又有并发查询的应用&#xff0c;如一些在线的OLTP系统。

8.0版本开始我们可以通过如下表查看死锁信息&#xff1a;

performance_schema.data_locks



推荐阅读
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
author-avatar
多少年都不会变
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有