mysql中锁的概念_MySQL中的锁1-基本概念

2024-02-03 13:40

本文主要是介绍mysql中锁的概念_MySQL中的锁1-基本概念,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是锁

在对共享资源并发访问时,锁用来保障数据的准确。通俗点理解,锁就类似于排队,Java中synchronized锁是在对象头上进行排队,分布式锁是在一个公用的存储服务上排队,而数据库中的锁是在所操作记录的对象上排队。

MySQL中锁的类型

各大主流数据库都会有锁的实现,而锁正是数据库区别于文件系统的特性之一。不仅不同数据库之间锁的实现不同,MySQL中不同存储引擎对于锁的实现也各不相同。

大体而言MySQL数据库中既有表锁,又有行锁。在Innodb存储引擎中会使用到下列这些锁:

Shared and Exclusive Lock

Intention Lock

Record Lock

Gap Lock

Next-Key Lock

Insert Intention Lock

AUTO-INC Locks

MyISAM中实现的锁是表锁,并发情况下的读没有问题,但是并发插入的性能很差。InnoDB实现的是行锁,锁定粒度小并发度高。MySQL默认的存储引擎是InnoDB,且官方目前打算不再继续对其他存储进行开发维护,所以这里我们讨论的锁都是基于InnoDB存储引擎。

锁都是锁在索引上的,无论是聚集索引(主键)还是二级索引

在InnoDB中行锁的模式有两种:

共享锁(S Lock),允许事务读取一行数据。

排他锁(X Lock),允许事务删除或者更新一行数据。

意向锁

除了行级别的锁,InnoDB中还支持表级别的锁。为了实现多粒度的锁(多粒度的锁表示在数据库中不但能实现行级别的锁,还可以实现页级别的锁,表级别的锁甚至数据库级别的锁),InnoDB还支持另外一种锁的模式,意向锁。意向锁主要是为了在一个事务中揭示下一行将被请求的锁类型。InnoDB同样支持两种意向锁:

意向共享锁(IS Lock),事务想要获取表中某几行的共享锁。

意向排他锁(IX Lock),事务想要获取表中某几行的排他锁。

意向锁的工作方式

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

MySQL加锁的方式是从上往下一层层加的。如果事务A要在记录1上加一把X锁,则步骤如下:

在记录1所在的数据库上加一把意向锁IX;

在记录1所在的表上加一把意向锁IX;

在记录1所在的页上加一把意向锁IX;

在记录1上加一把X锁。

InnoDB没有数据库级别的锁,也没有页级别的锁,InnoDB只能在表和记录上加锁,所以InnoDB的意向锁只能加在表上,即InnoDB中的意向锁都是表锁。

下面来看看共享锁、排他锁、意向共享锁、意向排他锁的兼容性

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

InnoDB中锁的兼容性

加锁以及查看

加锁

针对某条记录的修改和删除会隐式的加一把X锁,如果正对查询也想要加锁就需要在SQL语句中显示的指定。

查询操作通过在SQL语句的末尾处增加for update来加X锁

select * from t1 where a=1 for update;

查询操作通过在SQL语句的末尾处增加lock in share mode来加S锁

select * from t1 where a=1 lock in share mode;

锁超时

当产生锁竞争时,如果持有锁的一方迟迟不释放锁,这时请求锁的事务(或session)会一直等待锁的释放。但是这个等待锁的过程是有等待超时的,通过innodb_lock_wait_timeout变量进行设置,默认50s。也就是说等待50秒后还没有获取到锁就放弃等待,同时抛出错误ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

锁等待超时

查看

可以通过show engine innodb status\G;指令来查看加锁的情况,该指令会显示很多和innodb存储引擎相关的运行信息,其中TRANSACTIONS表示和锁相关的信息。默认显示的情况如下:

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

如果想要显示更详细的信息,可以将innodb_status_output_locks参数打开,在MySQL5.7中其默认是关闭的。

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

打开之后我们可以看到关于锁更详细的信息

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

-- Record lock : 表示是锁住的记录

-- heap no 2 PHYSICAL RECORD: n_fields 5 : 表示锁住记录的heap no 为2的物理记录,由5个列组成

-- compact format : 表示这条记录存储的格式(Dynamic其实也是compact的格式)

-- info bits : 0 -- 表示这条记录没有被删除; 非0 -- 表示被修改或者被删除(32)

在MySQL5.7之后的版本中,我们可以通过sys库下的innodb_lock_waits表来查看更详细的信息,注意只有当产生了锁等待时该表中才会有记录。

select * from innodb_lock_waits\G;

*************************** 1. row ***************************

wait_started: 2018-07-15 12:06:27 -- 开始的时间

wait_age: 00:00:09 -- 等待的时间

wait_age_secs: 9 -- 等待的秒数

locked_table: `test`.`t1` -- 锁主的表(意向锁)

locked_index: GEN_CLUST_INDEX -- 锁住的是系统生成的聚集索引,锁都是在索引上的

locked_type: RECORD -- 锁的类型,记录锁

waiting_trx_id: 421992807332576 -- 等待锁的事务ID

waiting_trx_started: 2018-07-15 12:06:27

waiting_trx_age: 00:00:09

waiting_trx_rows_locked: 1

waiting_trx_rows_modified: 0

waiting_pid: 13

waiting_query: select * from t1 where a=2 lock in share mode -- 等待锁的SQL语句

waiting_lock_id: 421992807332576:25:3:2 -- 事务ID:space:page_no:heap_no

waiting_lock_mode: S -- 等待的锁的模式

blocking_trx_id: 3338

blocking_pid: 12

blocking_query: NULL

blocking_lock_id: 3338:25:3:2

blocking_lock_mode: X -- 阻塞的锁的类型

blocking_trx_started: 2018-07-15 12:04:41

blocking_trx_age: 00:01:55

blocking_trx_rows_locked: 2

blocking_trx_rows_modified: 0

sql_kill_blocking_query: KILL QUERY 12

sql_kill_blocking_connection: KILL 12 -- 给出了建议

1 row in set, 3 warnings (0.00 sec)

下面列举一下通过show engine innodb status\G指令看到的各种锁的样子。

1. 意向锁

TABLE LOCK table `test`.`t3` trx id 3962 lock mode IX

2. Record Locks

RECORD LOCKS space id 39 page no 3 n bits 72 index PRIMARY of table `test`.`t3` trx id 3962 lock_mode X locks rec but not gap

2.1 从index PRIMARY可以看出该锁加在主键上

2.2 记录锁除了lock_mode X locks rec but not gap还有lock_mode S locks rec but not gap

3. Gap Locks

RECORD LOCKS space id 39 page no 5 n bits 72 index c of table `test`.`t3` trx id 3962 lock_mode X locks gap before rec

4. Next-Key Locks

RECORD LOCKS space id 39 page no 5 n bits 72 index c of table `test`.`t3` trx id 3962 lock_mode X

5. Insert Intention Locks

RECORD LOCKS space id 279 page no 3 n bits 72 index PRIMARY of table `test`.`t3` trx id 133587907 lock_mode X insert intention waiting

6. AUTO-INC Locks

TABLE LOCK table xx trx id 7498948 lock mode AUTO-INC waiting

读与MVCC

我们知道如果某行数据加了X锁, 就没法加S锁,即没法读了,不过在实际情况中一般数据库中都允许并发读的,即使要读取的记录上存在X锁。普通的读操作(非for update和lock in share mode)不会加锁。那么在MySQL中如何保障存在DDL的并发操作中读的一致性呢?Innodb使用了MVCC技术来保证读的一致性。

MVCC (Multiversion Concurrency Control),即多版本并发控制技术,它使得大部分支持行锁的事务引擎,不再单纯的使用行锁来进行数据库的并发控制,取而代之的是把数据库的行锁与行的多个版本结合起来,只需要很小的开销,就可以实现非锁定读,从而大大提高数据库系统的并发性能

163c4df21185?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

如果要读取的行上存在X锁,这时读操作不会等行上X锁的释放,而是去读取行的一个快照版本。由于没有事务会对快照数据进行修改,所以对于快照的读取是不用上锁的。

在read committed和repeatable read的事务隔离级别中,都是使用MVCC进行读操作。不过这两种隔离级别在选择哪个快照版本进行读取问题上存在区别,区别如下:

read committed选择最新的快照版本进行读(事务A),如果其他事务(事务B)对要读取的行进行了更新并提交。则在事务A再进行读时读取到的数据版本是事务B提交修改后形成的最新快照版本。

repeatable read读取的是事务(事务A)一开始时记录的快照版本,即使后面事务B对数据进行了修改并提交,只要事务A没有提交,那么在事务A中读取的版本依然是一开始的快照版本。

这也就能说明为啥在read committed中存在不可重复读现象,而repeatable read不存在。

MVCC实现读是不需要加锁的,MySQL当中除了MVCC的方式之外,我们还可以通过显示的加锁来保证并发过程中数据读取的一致性。可以通过下面两种方式显式的加锁:

select ... for update; 加X锁

select ... lock in share mode; 加S锁

这两种形式的查询语句要放在事务当中,一旦事务提交了,锁也就释放了。

这篇关于mysql中锁的概念_MySQL中的锁1-基本概念的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/674330

相关文章

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

SQL Server中行转列方法详细讲解

《SQLServer中行转列方法详细讲解》SQL行转列、列转行可以帮助我们更方便地处理数据,生成需要的报表和结果集,:本文主要介绍SQLServer中行转列方法的相关资料,需要的朋友可以参考下... 目录前言一、为什么需要行转列二、行转列的基本概念三、使用PIVOT运算符进行行转列1.创建示例数据表并插入数

MySQL MHA集群详解(数据库高可用)

《MySQLMHA集群详解(数据库高可用)》MHA(MasterHighAvailability)是开源MySQL高可用管理工具,用于自动故障检测与转移,支持异步或半同步复制的MySQL主从架构,本... 目录mysql 高可用方案:MHA 详解与实战1. MHA 简介2. MHA 的组件组成(1)MHA

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

MySQL基本表查询操作汇总之单表查询+多表操作大全

《MySQL基本表查询操作汇总之单表查询+多表操作大全》本文全面介绍了MySQL单表查询与多表操作的关键技术,包括基本语法、高级查询、表别名使用、多表连接及子查询等,并提供了丰富的实例,感兴趣的朋友跟... 目录一、单表查询整合(一)通用模版展示(二)举例说明(三)注意事项(四)Mapper简单举例简单查询

Nginx概念、架构、配置与虚拟主机实战操作指南

《Nginx概念、架构、配置与虚拟主机实战操作指南》Nginx是一个高性能的HTTP服务器、反向代理服务器、负载均衡器和IMAP/POP3/SMTP代理服务器,它支持高并发连接,资源占用低,功能全面且... 目录Nginx 深度解析:概念、架构、配置与虚拟主机实战一、Nginx 的概念二、Nginx 的特点

MySQL中的DELETE删除数据及注意事项

《MySQL中的DELETE删除数据及注意事项》MySQL的DELETE语句是数据库操作中不可或缺的一部分,通过合理使用索引、批量删除、避免全表删除、使用TRUNCATE、使用ORDERBY和LIMI... 目录1. 基本语法单表删除2. 高级用法使用子查询删除删除多表3. 性能优化策略使用索引批量删除避免

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE