mysql中锁机制的最全面讲解

目录
  • 前言
  • 全局锁
    • 全库逻辑备份
    • FTWRL和set global readonly=true的区别
  • 表级锁
    • MDL锁
  • 行锁
  • 死锁
    • 记录锁
    • 间隙锁
    • 临键锁
  • 乐观锁和悲观锁
  • 总结

前言

根据加锁的粒度区分

  • 全局锁
  • 表级锁
  • 行锁
    • 记录锁
    • 间隙锁
    • 临键锁

根据加锁的场景

  • 乐观锁
  • 悲观锁

全局锁

锁对象是:整个数据库实例

Flush tables with read lock (FTWRL)-会让整个库处于只读状态

使用场景: 做全库逻辑备份

全库逻辑备份

为什么要进行全局锁才能进行数据备份呢?

就比如售卖,我一张表记录发货,一张表记录扣款.结果我在备份发货记录表.这个时候有人买东西了,只扣款了但是没有发货记录.这个显然是不行的

官方自带的逻辑备份工具是mysqldump。当mysqldump使用参数–single-transaction的时候,导 数据之前就会启动一个事务,来确保拿到一致性视图。而由于MVCC的支持,这个过程中数据是 可以正常更新的。但是这个是基于事务的基础上的,针对myisam数据引擎就不可用,那么就有可能出现有的表不是基于innoDB的数据引擎

当然,如果全部都是innodb的数据引擎表,那么,还是使用默认的mysqldump增加参数–single-transaction来进行全局逻辑备份的好

FTWRL和set global readonly=true的区别

  1. readonly会在别的逻辑中参与使用(不同系统不一样)
  2. ftwrl可以在客户端链接断开时,自动释放锁.防止造成死锁问题

表级锁

命令:lock table {tableName} read/write(write比read权限大,能write当然能read),unlock table解锁

锁住的资源只允许当前的线程可以执行对应的操作.且当前线程只能对锁住的表进行对应的操作

例如:lock table t1 read,则当前线程只能读不能写,其他线程不能读不能写

MDL锁

不需要显式使用,在访问表时自动加上(为了防止表结构变更带来的问题)

在对一张表进行增删改查时上MDL读锁,在对一张表的结构进行变更时上MDL写锁

  • MDL读锁(共享锁),锁之间不互斥.所以可以允许多个线程进行同时的增删改查
  • MDL写锁(排它锁),这个锁和其他读写锁都互斥.也就是当前数据变更或者查询或者结构变更,都必须等其他的MDL写锁释放后才能执行

行锁

行锁是引擎层,各个引擎自己实现的(MyISAM不支持行锁,所以该引擎只能一次进行一个线程的update操作)

在事务中:行锁会在需要使用某一行或多行数据时加上,但是所有的行锁都会在该事务提交才会释放也就是说,别的线程需要访问改行数据,就需要等待线程的事务提交之后才能访问

举例:

线程A执行以下操作
begin;
update t1 set a=1 where id=1;

update t2 set b=2 where id=2;

commit

这个时候线程A分别对t1的id=1上锁和t2的id=2上锁.如果此时线程B访问t1的id=1是无法访问的,即使第一条语句已经执行完成了
线程B只有在线程A进行了commit操作之后才能获取其中的数据

所以,对于我们来说需要注意的点就是:在进行事务操作时,如果update没有顺序操作,那么就尽量将访问最多的那条语句最后执行(因为上锁是顺序上的,但是释放锁是一起释放的)

特点 表锁 行锁
加锁层面 mysql的server层 数据引擎层
引擎 MyISAM、innoDB InnoDB
特点 不会死锁、开销小、加锁快、锁粒度大 易死锁、开销大、加锁慢、锁粒度小

死锁

很多情况都回引起死锁,大部分都是针对数据库操作有问题才会导致.比如

线程A和线程B都针对id=1和id=2进行修改并开启事务

线程A先修改了id=1导致id=1被线程A上锁

线程B修改了id=2导致id=2被县城B上锁

此时线程A要等待id=2释放锁后执行对id=2的操作
而线程B要等待id=1释放锁后怼id=1的操作

从而达到了一个循环死锁的情况

处理这种问题有两个策略:

  1. 直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout(默认50s)来设置。这个不能设置太短,如果不是死锁呢?
  2. 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事 务得以继续执行。将参数innodb_deadlock_detect设置为on(默认就是on),表示开启这个逻辑。

记录锁

属于行锁的一种情况

针对的是事务在加锁后锁住的某一条记录信息

触发情况:查询条件精准命中且命中的条件字段是唯一的

例如:update t1 set name="张三" where id=12138

作用:记录在被当前事务管理时,加上锁之后不会被其他事务获取产生“重复读”和“数据脏读”的问题

间隙锁

属于行锁的一种情况

间隙的意思就是between中的数据

在主键索引id中有多个数据未填充,这个时候如果两个线程A和B,A在查询0-10之间的数据,而B在往id=3插入数据,就会造成数据脏读的问题

所以在进行between等范围查找的是事务时候,会加间隙锁进行约束

临键锁

临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住。

(临就是相邻的意思)

乐观锁和悲观锁

概念 乐观锁 悲观锁
概念 假定不会发生并发冲突
只在提交时判断下是否有数据问题
假定会发生并发冲突
从而上锁
实现层面 业务代码层面,自己实现
(需要结合具体业务逻辑)
mysql数据库自身实现
并发情况 并发大 并发小
实现方式 在数据库中增加版本号字段,
提交时判断操作前的版本号和当前版本号是否一致
共享锁:select lock xxxxxx
排它锁:select xxxx for update
其他 mysql中的synchronized其实就是排它锁
共享锁:运行其他线程查不允许增删改
排它锁:增删改都不允许

总结

到此这篇关于mysql中锁机制的文章就介绍到这了,更多相关mysql锁机制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL数据库锁机制原理解析

    在并发访问情况下,很有可能出现不可重复读等等读现象.为了更好的应对高并发,封锁.时间戳.乐观并发控制(乐观锁).悲观并发控制(悲观锁)都是并发控制采用的主要技术方式. 锁分类 ①.按操作划分:DML锁,DDL锁 ②.按锁的粒度划分:表级锁.行级锁.页级锁 ③.按锁级别划分:共享锁.排他锁 ④.按加锁方式划分:自动锁.显示锁 ⑤.按使用方式划分:乐观锁.悲观锁 乐观锁和悲观锁 乐观并发控制和悲观并发控制是并发控制采用的主要方法.乐观锁和悲观锁不仅在关系数据库里应用,在Hibernate.Memca

  • MySQL隔离级别和锁机制的深入讲解

    目录 简述: 1. 事务的四大特性 2.多事务并发带来的问题 3.事务的隔离级别 4.演示不同隔离级别出现的问题 读未提交 读已提交 可重复读 串行化 5.锁机制 间隙锁 临建锁 排他锁 总结 简述: 我们的MySQL一般会并发的执行多个事务,多个事务可能会并发的对同一条或者同一批数据进行crud操作;可能就会导致我们平常所说的脏读.不可重复读.幻读这些问题. 这些问题的本质都是MySQL多事务并发问题,为了解决多事务并发问题,MySQL设计了锁机制.MVCC多版本并发控制隔离机制.以及事务隔离

  • MySQL InnoDB中的锁机制深入讲解

    写在前面 数据库本质上是一种共享资源,因此在最大程度提供并发访问性能的同时,仍需要确保每个用户能以一致的方式读取和修改数据.锁机制(Locking)就是解决这类问题的最好武器. 首先新建表 test,其中 id 为主键,name 为辅助索引,address 为唯一索引. CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` int(11) NOT NULL, `address` int(11) NOT NULL, P

  • MySQL锁机制与用法分析

    本文实例讲述了MySQL锁机制与用法.分享给大家供大家参考,具体如下: MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁:BDB存储引擎采用的是页面锁,但也支持表级锁:InnoDB存储引擎既支持行级锁,也支持表级锁,但默认情况下采用行级锁. MySQL这3种锁的特性可大致归纳如下: (1)表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. (2)行级锁:开销大,加锁慢:会出现死锁:

  • mysql中的锁机制深入讲解

    前言 为了保证数据的一致完整性,任何一个数据库都存在锁定机制.锁定机制的优劣直接应想到一个数据库系统的并发处理能力和性能,所以锁定机制的实现也就成为了各种数据库的核心技术之一. 大概几个月之前项目中用到事务,需要保证数据的强一致性,期间也用到了mysql的锁,但当时对mysql的锁机制只是管中窥豹,所以本文打算总结一下mysql的锁机制. 本文主要论述关于mysql锁机制,mysql版本为5.7,引擎为innodb,由于实际中关于innodb锁相关的知识及加锁方式很多,所以没有那么多精力罗列所有

  • mysql中锁机制的最全面讲解

    目录 前言 全局锁 全库逻辑备份 FTWRL和set global readonly=true的区别 表级锁 MDL锁 行锁 死锁 记录锁 间隙锁 临键锁 乐观锁和悲观锁 总结 前言 根据加锁的粒度区分 全局锁 表级锁 行锁 记录锁 间隙锁 临键锁 根据加锁的场景 乐观锁 悲观锁 全局锁 锁对象是:整个数据库实例 Flush tables with read lock (FTWRL)-会让整个库处于只读状态 使用场景: 做全库逻辑备份 全库逻辑备份 为什么要进行全局锁才能进行数据备份呢? 就比如

  • 详解MySQL中EXPLAIN解释命令及用法讲解

    1,情景描述:同事教我在mysql中用explain,于是查看了一番返回内容的含义 2,现就有用处的内容做如下记录: 1,explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: explain select count(DISTINCT uc_userid) as user_login from user_char_daily_gameapp_11 where uc_d

  • MySQL中锁的相关问题

    锁分类: 从对数据操作的粒度分 : 表锁:操作时,会锁定整个表.行锁:操作时,会锁定当前操作行. 从对数据操作的类型分: 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响.写锁(排它锁):当前操作没有完成之前,它会阻断其他客户端的 行表锁特点: MyISAM 表锁: 如何加表锁 MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE.DELETE. INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,

  • MySQL中MVCC机制的实现原理

    目录 前言 什么是当前读和快照读? MVCC的实现原理 前言 MVCC全称为Multi Version Concurrency Control,直译为多版本并发控制,是MySQL中一种并发控制的方法,他主要是为了提高数据库的读写性能,用更好的方式去处理读写冲突. 什么是当前读和快照读? 在讲述MVCC机制实现原理之前,我们先了解一下当前读和快照读 当前读: 其实也很容易理解,当前读指的就是读取的是最新的记录,读取的时候还需要保证其他事务不能修改当前记录,所以会对读取的记录进行加锁处理 例如:se

  • MySql中sql语句执行过程详细讲解

    目录 前言: sql语句的执行过程: 查询缓存: 分析器: 优化器: 执行器: 总结 前言: 很多人都在使用mysql数据库,但是很少有人能够说出来整个sql语句的执行过程是怎样的,如果不了解执行过程的话,就很难进行sql语句的优化处理,也很难设计出来优良的数据库表结构.这篇文章主要是讲解一下sql语句的执行过程. sql语句的执行过程: 客户端.连接器.分析器.优化器.执行器.存储引擎几个阶段. 连接器的作用:管理链接.权限验证的处理. 分析器的作用:词法分析.语法分析. 优化器的作用:执行计

  • mysql中影响数据库性能的因素讲解

    关于数据库性能的故事 面试时多多少少会讲到数据库上的事情,"你对数据库的掌握如何?",什么时候最考验数据库的性能,答应主要方面上讲就是大数据量的读写时,而电商类的大促活动就是考验各自的数据库性能的时候啦. 对于web服务器而言,数据量大时,我们可以简单的通过横向扩展来减少单个服务器的负担,但是对于数据库服务器来说就没有那么简单了,他们不可能做到轻易的横向扩展,这样也违背了数据库的完整性与一致性的原则,那么我们的数据库架构该如何搭建呢? 对于大促类活动而言,不管是产品多好.策划多成功,如

  • MySQL中Innodb的事务隔离级别和锁的关系的讲解教程

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会

随机推荐