一:锁类型(加锁范围区分类型)

  - MySQL里面的锁可以分为:全局锁、表级锁、行级锁。

二:全局锁

  - 作用

    -  对整个数据库实例加锁。

  - 加锁方式

    - MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)

    - 这个命令可以使整个库处于只读状态。

    - 使用该命令之后,数据更新语句、数据定义语句和更新类事务的提交语句等操作都会被阻塞。

  - 使用场景

    - 全库逻辑备份。(加锁的目的是为了在备份时候 保证数据视图的一致性)

  - 风险(指的使用全局锁风险)

    - 如果在主库备份,在备份期间不能更新,业务暂停。

    - 如果在从库备份,备份期间不能执行主库同步的binlog,导致主从延迟。

  - 其他方法(可以代替全局锁的方法)

    - 官方自带的逻辑备份工具mysqldump

      - 当mysqldump使用参数--single-transaction的时候,会启动一个事务,确保拿到一致性视图。

      - 而由于MVCC的支持,这个过程中数据是可以正常更新的。

      - 一致性读是好,但是前提是引擎要支持这个隔离级别。

    - 如果要全库只读,为什么不使用set global readonly=true的方式?

      - 在有些系统中,readonly的值会被用来做其他逻辑,比如判断主备库。所以修改global变量的方式影响太大。

      - 在异常处理机制上有差异。如果执行FTWRL命令之后由于客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态

      - 而将整个库设置为readonly之后,如果客户端发生异常,则数据库就会一直保持readonly状态,这样会导致整个库长时间处于不可写状态,风险较高。

三:表级锁

  - MySQL里面表级锁有两种

    - 表锁(lock table)

    - 元数据锁(meta data lock,MDL)

  - 表锁

    - 作用

      - 防止 DDL 之间的冲突

    - 加锁方式

      - lock tables ... read/write

      - 可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。

    - 注意

      - lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

        - 例如:线程 A 执行了 lock tables t1 read, t2 write;

          - 则其他线程写 t1、读写 t2 的语句都会被阻塞。

          - 同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。

          - 连写 t1 都不允许,自然也不能访问其他表。

  - 元数据锁(MDL)

    - 作用

      - MDL作用是防止DDL和DML并发的冲突。

    - 加锁方式

      - 不需要显式使用,在访问一个表的时候会被自动加上。

      - 在对一个表做增删改查操作的时候,加MDL读锁。(可并发读)

      - 当要对表做结构变更操作的时候,加MDL写锁。(堵塞读写)

    - 可能产生的问题

      - 以下面的事务举例子

      - 

      - 分析一下上面事务可能产生的问题

        - session A 先启动,这时候会对表 t 加一个 MDL 读锁。

        - session B 需要的也是 MDL 读锁,因此可以正常执行。

        - session C 会被 blocked(阻塞),是因为 session A 的 MDL 读锁还没有释放,而 session C 需要 MDL 写锁,因此只能被阻塞。

      - 问题

        - 如果只有 session C 自己被阻塞还没什么关系,但是之后所有要在表 t 上新申请 MDL 读锁的请求也会被 session C 阻塞。

        - 因为 DML 的特性,所有对表的增删改查操作都需要先申请 MDL 读锁,就都被锁住,等于这个表现在完全不可读写了。

        - 如果某个表上的查询语句频繁,而且客户端有重试机制,也就是说超时后会再起一个新 session 再请求的话,这个库的线程很快就会爆满。

      

      - 原因

        - 事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。

  - 解决热点更新表的字段添加问题?(知道 MDL 可能产生的问题,我们要尝试解决在热点表添加字段,同时避免 MDL 锁的问题)

    - 应当尽量避免在业务高峰时,执行 DDL 语句

    - 解决长事务 (事务不提交,就会一直占着 MDL 锁。)

      - 在 MySQL 的 information_schema 库的 innodb_trx 表中,你可以查到当前执行中的事务。

      - 如果你要做 DDL 变更的表刚好有长事务在执行,要考虑先暂停 DDL,或者 kill 掉这个长事务。

    

    - 但是如果是热点表,请求频繁,而不得不加字段

      - 这时候 kill 可能未必管用,因为新的请求马上就来了。

      - 比较理想的机制是,在 alter table 语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到 MDL 写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。

      - 之后开发人员或者 DBA 再通过重试命令重复这个过程。

四:行级锁

  - 行级锁

    - 是在各个 存储引擎里自己实现的

  - 两阶段锁的概念是什么? 对事务使用有什么帮助?

    - 概念

      - 在 InnoDB 事务中,行锁是在需要的时候才加上的(一段)。

      - 但并不是不需要了就立刻释放, 而是要等到事务结束时才释放(二段)。

    - 帮助

      - 数据视图的一致性,保证隔离性。

  - 死锁的概念是什么? 举例说明出现死锁的情况.

    - 概念

      -  事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。

    - 死锁(A/B 事务相互等待)

      • A 事务                         B 事务
        update A = (A 加锁)
        update B = (B 加锁)
        update B = (等待B事务释放锁)
        update A = (等待A事务释放锁)
        死锁

  - 死锁的处理策略?

    死锁等待

      - 当事务遇到死锁时候,会一直等待,直到超时。

      - 参数 innodb_lock_wait_timeout 设置死锁等待时间(InnoDB默认是50s)。

    - 死锁检测

      - 当发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。     

      - 将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑(默认是开启状态)。

  - 等待超时处理死锁的机制什么?有什么局限?

    - 机制

      - 出现死锁后,事务双方相互等待,直到有一个事务超时,另一个事务获得锁,继续执行。

    - 局限

      - 业务中出现大量的超时事务,而等待锁的过程中也会导致业务等待。

   死锁检测处理死锁的机制是什么? 有什么局限?

    - 机制

      - 每当一个事务被锁的时候。就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。

    - 局限

      - 每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,这是一个时间复杂度是 O(n) 的操作。

      - 假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。

      - 虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源。因此,你就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。

  - 有哪些思路可以解决热点更新导致的并发问题?(知道了死锁的机制处理之后)

    - 如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关闭掉。

      - 可能产生大量的超时事务,一般不建议采用

    - 控制并发

      - 根据上面的分析,你会发现如果并发能够控制住,比如同一行同时最多只有 10 个线程在更新,那么死锁检测的成本很低,就不会出现这个问题。

      - 通过中间件或者其他方式,控制并发度,对应相同行的更新,在进入引擎之前排队。这样在InnoDB内部就不会有大量的死锁检测工作了。

    - 业务拆分

      - 比如把账单的一条数据,拆分成10条,最后求和。更新时候,选择一条进行操作。

      - 这样可以减少锁冲突,并发度也会提高,但是业务复杂度可能会大大提高。

《Mysql 锁 - 概述》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. CF891C Envy【最小生成树】

    题目链接 我们知道,根据Kruskal的贪心,对于最小生成树,每一种权值的边数是一样的,而且如果将\(\leq x\)的边做最小生成树,合法方案的联通性是一样的.所以我们可以对于所有边分开考虑. 对于 ...

  2. Mac 下 安装 Nginx

    ---恢复内容开始--- Mac 下 安装nginx 首先确定自己有安装homebrew 安装 nginx brew install nginx 启动nginx 1.15版本下 安装是 直接在ngin ...

  3. vue中封装一个倒计时

    <template> <div class="countDownBox"> <div class="row resetStyle" ...

  4. ROS文件系统级

    ROS的安装就不介绍了,官方教程是最好的:点击打开链接 ROS是机器人操作系统,它应该有自己的工程结构,Linux系统的文件系统如下: 而ROS的文件系统级如下: 接下来逐一介绍它们: 1. catk ...

  5. liunx系统下crontab定时启动Scrapy爬虫程序

    定时启动爬虫 # 查看命令得绝对路径 # which scrapy # cd到爬虫得项目目录下 + scrapy命令得绝对路径 + 启动命令 */5 * * * * cd /opt/mafengwo/ ...

  6. scanf和fgets比较

    scanf 长度限制 #include<stdio.h> int main() { char food[5]; printf("Enter food"); scanf( ...

  7. CSAW Quals CTF 2017-scv

    目录 程序基本信息 程序漏洞 整体思路 exp脚本 内容参考 程序基本信息 64位动态链接程序,开启了栈溢出和数据段不可执行保护 程序漏洞 read函数很明显的栈溢出漏洞 整体思路 由于题目给了lib ...

  8. 性能测试工具gperftools使用

    https://blog.csdn.net/10km/article/details/83820080 https://blog.51cto.com/wulingdong/2043898 https: ...

  9. Linux中强大的top命令

    top命令算是最直观.好用的查看服务器负载的命令了.它实时动态刷新显示服务器状态信息,且可以通过交互式命令自定义显示内容,非常强大. 在终端中输入top,回车后会显示如下内容:   top - 21: ...

  10. Linux如何使用shell命令检测PHP木马防止脚本木马的破坏

    1.一句话查找PHP木马 代码如下 # find / -name "*.php" |xargs egrep "phpspy|c99sh|milw0rm|eval\(gun ...