《MySQL45讲》笔记—锁

数据库锁设计初衷是处理并发问题,作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则,而锁就是用来实现这些访问规则的重要数据结构

  • 根据加锁的范围,MySQL里面的锁大致可以分为全局锁、表级锁和行锁三类。

全局锁

MySQL提供了一个加全局读锁的方法,命令是Flush tables with read lock (FTWRL),当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

使用场景

全库逻辑备份,也就是把整个库每个表都select出来存成文本。一致性读是好,但前提是引擎要支持这个隔离级别。比如,对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL命令了。

也就是说,如果有的表使用了不支持事务的引擎,那么备份就只能通过FTERL方法;如果所有表使用事务引擎的话,可以使用一个官方自带的逻辑备份工具mysqldump,使用参数-single-transaction,导数据之前就会启动一个事务,来确保拿到一致性视图,由于MVCC支持,这个过程中的数据是可以正常更新的。

表级锁

表锁

表锁的语法是lock tables …read/write,也可以使用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。lock tables语法除了会限制别的线程读写之外,也限定了本线程接下来的操作对象。在还没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式。而对于InnoDB这种支持行锁的引擎,一般不使用lock tables命令来控制并发,毕竟锁住整个表的影响面还是太大。

元数据锁

不需要显式使用,在访问一个表的时候会被自动加上。MySQL 5.5版本中引入了MDL,当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁,可以保证读写的正确性。

  • 读锁之间不互斥,所以可以有多个线程同时对一张表进行增删改查。
  • 读写锁之间、写锁之间是互斥的,用来保证变更结构表操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

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

如何安全的给小表加字段
  • 首先要解决长事务,事务不提交,就会一直站着MDL锁。在MySQL的information_schema库的innodb_trx表中,你可以查到当前执行中的事务,如果你要做DDL变更的表刚好有长事务在执行,要考虑先暂停DDL,或者kill掉这个长事务。

但考虑一下这个场景。如果你要变更的表是一个热点表,虽然数据量不大,但是上面的请求很频繁,而你不得不加个字段,你该怎么做呢?
这时候kill可能未必管用,因为新的请求马上就来了。比较理想的机制是,在alter table语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到MDL写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后开发人员或者DBA再通过重试命令重复这个过程。

MariaDB已经合并了AliSQL的这个功能,所以这两个开源分支目前都支持DDL NOWAIT/WAITn这个语法。

行锁

MySQL的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如MyISAM引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的,这也是MyISAM被InnoDB替代的重要原因之一。

两阶段锁

在InnoDB事务中,行锁是在需要的时候才加上的,但是并不是不需要了就立刻释放,而是要等到事务结束的时候才释放,这个就是两阶段锁协议。
所以,如果事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

死锁和死锁检测

不同线程出现循环资源以来,涉及的线程都在等待别的线程释放资源。然后无限等待。

策略

  • 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置,默认是50
  • 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect设置为on,表示开启这个逻辑.默认是on。也就是说,在发生死锁的时候,可以快速发现并且进行处理,但是这样也是有额外负担的,每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后按段是否出现了循环等待,最后判断是否出现了循环等待,也就是死锁。

每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,这是一个时间复杂度是O(n)的操作。假设有1000个并发线程要同时更新同一行,那么死锁检测操作就是100万这个量级的。虽然最终检测的结果是没有死锁,但是这期间要消耗大量的CPU资源。因此,你就会看到CPU利用率很高,但是每秒却执行不了几个事务。

如何解决由这种热点行更新导致的性能问题呢?

  • 确保业务不会出现死锁
  • 考虑在中间件实现:对于相同行的更新,在进入引擎之前排队,这样在存储引擎内部就不会由大量死锁检测工作了。
  • 将一行改成逻辑上的多行来减少锁冲突。以影院账户为例,可以考虑放在多条记录上,比如10个记录,影院的账户总额等于这10个记录的值的总和。这样每次要给影院账户加金额的时候,随机选其中一条记录来加。这样每次冲突概率变成原来的1/10,可以减少锁等待个数,也就减少了死锁检测的CPU消耗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/61860.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多线程案例(3)-定时器

文章目录 多线程案例三三、 定时器 大家好,我是晓星航。今天为大家带来的是 多线程案例三 相关的讲解!😀 多线程案例三 三、 定时器 定时器是什么 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就…

Python Opencv实践 - 基本图像IO操作

import numpy as np import cv2 as cv import matplotlib.pyplot as plt#读取图像 #cv2.IMREAD_COLOR: 读取彩色图像,忽略alpha通道,也可以直接写1 #cv2.IMREAD_GRAYSCALE: 读取灰度图,也可以直接写0 #cv2.IMREAD_UNCHANGED: 读取…

SQL ASNI where from group order 顺序

SQL语句执行顺序: from–>where–>group by -->having — >select --> order 第一步:from语句,选择要操作的表。 第二步:where语句,在from后的表中设置筛选条件,筛选出符合条件的记录。 …

JavaScript实践:用Canvas开发一个可配置的大转盘抽奖功能

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已…

【瑞吉外卖项目复写】基本部分复写笔记

Day1 瑞吉外卖项目概述 mysql的数据源配置 spring:datasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/regie?serverTimezoneAsia/Shanghai&useUnicodetrue&characterEncodingutf-8&zeroDateTimeBehaviorconvertTo…

【C++】深入浅出STL之vector类

文章篇幅较长,越3万余字,建议电脑端访问 文章目录 一、前言二、vector的介绍及使用1、vector的介绍2、常用接口细述1)vector类对象的默认成员函数① 构造函数② 拷贝构造③ 赋值重载 2)vector类对象的访问及遍历操作① operator[]…

windows永久暂停更新

目录 1.winr,输入regedit打开注册表 2.打开注册表的这个路径: 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键空白地方新建QWORD值命名为:FlightSettingsMaxPauseDays 3.双击FlightSettingsMaxPauseDays,修改里面的值为100000,右边基数设置…

区块链实验室(14) - 编译FISCO-BCOS

FISCO-BCOS是一种区块链平台,与Hyperledger和Ethereum有些不同,详见FISCO BCOS 区块链 编译FISCO BCOS源码的目的是修改或者新增其中功能模块,进行对比实验,验证新想法、新创意的效果。编译的步骤很简单,按技术文档一…

JavaWeb三大组件 —— Servlet

目录 servlet 注册servlet 父pom pom文件 1、通过注解注册 2、使用ServletRegistrationBean注册 API三生三世 第一生Servlet 第二生SpringMVC 今生SpringBoot servlet Servlet的作用: 接受请求参数、处理请求,响应结果,(就…

flask中的应用上下文

flask中的应用上下文 Flask应用上下文主要包含两个对象:current_app和g。这两个对象在处理请求期间都是全局可访问的,但在每个请求结束时都会被重置。 current_app:这是当前激活的Flask应用的实例。在大多数情况下,你可以将其视为…

回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SO-CNN-GRU蛇群算法优化卷积门控循…

go-zero超强工具goctl的常用命令api,rpc,model及其构建的服务解析

goctl api 详情移步: go-zero的路由机制解析 基于go-zero的api服务刨析并对比与gin的区别 goctl rpc goctl支持多种rpc,较为流行的是google开源的grpc,这里主要介绍goctl rpc protoc的代码生成与使用。 protoc是grpc的命令,作用…

uniapp uview文件上传的文件不是文件流,该如何处理?用了uni.chooseImage预览功能要如何做

在使用uniapp开发,运用的ui是用uview,这边需要做一个身份认证,如下图 使用的是uview的u-upload组件,可是这个组件传给后端的不是文件流 后端接口需要的是文件流格式,后面使用了uniapp的选择图片或者拍照的api&#x…

UltraToolBars Crack,动画菜单和多种显示样式

UltraToolBars Crack,动画菜单和多种显示样式 创建模仿Microsoft Office 2000外观的健壮应用程序。 UltraToolBars包括11个用于创建可自定义工具栏的界面增强控件,包括:个性化菜单、弹出型工具栏、集成选项卡控件等。PictureRegion技术使表单和组件能够采…

实现vscode上用gdb调试stm32

实现vscode上用gdb调试stm32 这周负责编写设备的某个模块,其中遇到了一些变量地址不正确的错误,按理这种底层变量错误用gdb一类的调试器就能很快查到,可是初入嵌入式一行,此C语言非彼C语言,对于gdb怎么对接到项目上根…

微服务系列<3>---微服务的调用组件 rpc 远程调用

什么是rpc调用,让我们调用远程方法就像调用本地方法一样 这就属于rpc调用 rpc是针对于本地来说的 调用远程方法根调用本地方法一样 如果能达到这种效果 就是rpc调用如果达到一种效果 调用远程和调用本地一样 他就是一种rpc框架2个微服务 之间发的调用 我们之前通过ribbon的方式…

【数模】预测模型

一、灰色系统 白色系统:系统信息完全明确灰色系统:系统部分信息已知,部分信息未知 对在一定范围内变化的、与时间有关的灰色过程进行预测。过程:原始数据找规律→生成强规律性的数据序列→建立微分方程来预测未来趋势 黑色系统&a…

JavaWeb项目工程结构介绍

介绍idea创建Web项目工程下的项目结构(新建的web工程) 了解目录大致作用 一级目录 :.idea、out、src、web、工程名.iml .idea目录:记录了IntelliJ IDEA 的配置目录,包含项目的配置信息、工程设置、构建配置等。它是用来存储项目…

谈谈网络安全

目录 1.概念 2.发展现状 3.主要问题 1.概念 网络安全是指保护计算机网络和其中的数据免受未经授权访问、损坏、窃取或破坏的过程和技术。网络安全涉及预防和检测潜在的威胁和漏洞,并采取措施保护网络的机密性、完整性和可用性。 网络安全的概念包括以下几个方面&am…

Vue系列第七篇:Element UI之el-main,el-table,el-dialog,el-pagination,el-breadcrumb等控件使用

本篇实现主页面功能,包括主页面排版布局,学生管理模块实现,后台接口实现等功能。 目录 1.运行效果 1.1登录页面 1.2主页面 1.3学生管理 - 信息列表 1.4学生管理 - 信息管理 1.5学生管理 - 作业列表 1.6学生管理 - 作业管理 2.前端代码…
最新文章