安全基础 --- MySQL数据库的《锁》解析

news2024/11/30 12:33:40

MySQL的ACID

(1)ACID是衡量事务的四个特性

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

(2)解析

原子性:语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是用原子性来定义的。(实现主要基于 undo log)

持久性:保证事务提交后不会因宕机导致数据丢失。(实现主要基于 redo log)

隔离性:保证事务执行尽可能不受其他事务影响;InooDB默认的隔离级别是RR,RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于 undo log 的版本链、ReadView)

一致性:事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障

mysql的锁机制

加锁机制:乐观锁和悲观锁

(1)悲观锁

悲观锁:又称悲观并发控制,指的是数据被外界修改持保持态度,整个事务处理中,将数据进行锁定,直到事务处理完毕,才释放锁。

PS:悲观锁认为并发事物会导致问题,屏蔽一切可能违反数据一致性的操作。

特点:完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁,然后进行数据操作,最后再解锁,加锁释放锁的过程会有消耗,所以性能不高;

(2)乐观锁

乐观锁:假设认为数据一般情况下不会造成冲突,所以在数据提交更新时候,才回正式对数据的冲突与否进行检查。

实现方式(常见):

  1. 版本号:表中新增一个版本号字段,每次数据更新都会修改版本号。更新数据会检查数据库中版本号与之前读取版本号是否一致,一致则允许修改
  2. 时间戳:类似于版本号的方式,使用数据库时间戳来实现。更新数据时会检查时间戳是否与之前读取的一致
  3. 基于字段判断:使用WHERE字句加上之前读取的字段值进行判断。更新行数为0,则表示数据已被其他事务修改,发生冲突

在提交更新之前检查是否有其他事务已经修改了该记录,如果发现修改,则会回滚更新并重试事务。否则,它会将更新提交到数据库。

兼容性:共享锁和排它锁

(1)排它锁

排它锁:又被称为写锁(简称X锁)。不能与其它事务共存,如一个事务获取了一个数据行的排它锁,其他事务就不能获取该行的其他锁,包括共享锁和排它锁。

实质:排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁

实现:

打开第一个命令行界面

set autocommit=0; ---> 关闭自动提交
select * from users where from id=1 for update; ---> 查询语句的同时增加排它锁

打开第二个命令行界面


进程阻塞,不会再去动这个进程,除非上级事务提交


上级事务已提交

查询结果显示

存在问题:用户的体验和性能。如果用排它锁锁住,所有的读、请求都会堵塞在这里,对系统压力较大。n等多个进程全部堵塞,在等待中,释放后这些进程就会开始竞争,其中一个进程竞争到,其他进程相当于什么都没干,系统性能已消耗。 ---  惊群效应

惊群效应:当你往一群鸽子中间扔一块食物,虽然最终只有一个鸽子抢到食物,但所有鸽子都会被惊动来争夺,没有抢到食物的鸽子只好回去继续睡觉, 等待下一块食物到来。这样,每扔一块食物,都会惊动所有的鸽子,即为惊群。

(2)共享锁

共享锁:又被称为读锁(简称S锁)。多个事务对于同一数据可以共享一把锁,都能访问到数据,但是仅只读不能修改。

共享锁相对更好理解一点,就是多个事务只能读数据不能改数据。

实现:

打开第一个命令界面

select * from users where id=1 lock in share mode; --->  做共享锁

打开第二个命令界面

update users set username='oupeng' where id=1; ---> 更新users表中id=1的username

存在问题:修改数据时,该共享锁认为该线程一定会被一定会被多个线程争抢,读线程不受影响,

PS:共享锁和排它锁都属于悲观锁

mysql事务隔离级别

MySQL 事务都是指在 InnoDB 引擎下

(1)级别分类

mysql有四个事务隔离级别,每个级别都有字符或数字编号

  • 读未提交(READ-UNCOMMITTED)| 0 :存在脏读,不可重复读,幻读的问题
  • 读已提交(READ-COMMITTED) | 1:解决脏读的问题,存在不可重复读,幻读的问题
  • 可重复读(REPEATABLE-READ) | 2:解决脏读,不可重复读的问题,存在幻读的问题,默认隔离级别,使用MVVC机制,实现可重复读
  • 序列化(SERIALIZABLE) | 3:解决脏读,不可重复读,幻读的问题,保证事务安全,但完全串行执行,性能最低

查看会话的事务隔离级别:

select @@global.tx_isolation, @@tx_isolation;

默认的隔离级别为可重复读

(2)解决实际问题

  • 脏读(Dirty Read)
    脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读。
  • 可重复读(Repeatable Read)
    可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。通常针对数据更新(UPDATE)操作。
  • 不可重复读(Non-Repeatable Read)
    对比可重复读,不可重复读指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这批数据并提交了。通常针对数据更新(UPDATE)操作。
  • 幻读(Phantom Read)
    幻读多是针对数据插入(INSERT)操作来说的。事务 A 按照一定条件进行数据读取, 期间事务 B 插入了相同搜索条件的新数据,事务 A 再次按照原先条件进行读取时,发现了事务 B 新插入的数据,称为幻读
脏读演示

<1> 开启A,B两个窗口,进行如下操作:

show variables like 'autocommit';  ----  查看当前的自动提交是否开启
set autocommit = off; --- 关闭自动提交

set session transaction isolation level read uncommitted; --> 设置当前会话隔离级别为“读未提交”
select @@tx_isolation; --> 查看当前隔离级别

start transcation; --- 开启事务,(begin; -- 显式开启事务)

<2> 修改数据进行查询

B:update users set username='123456' where id=1; --- 修改id=1的username为123456
A:select * from users where id=1; --- 在A窗口查询id=1的数据 



事务未关闭,显示数据已被更改,此时出现的问题即为脏读。

不可重复读演示

<1> 关闭A,B的自动提交机制,使用读已提交隔离级别,开启事务



<2> 修改数据进行查询

B:update users set username='oupengaaa' where id=1; --- 修改id=1的username为oupengaaa
A:select * from users where id=1; --- 在A窗口查询id=1的数据



​​​​​​id=1的username未发生改变,当B窗口修改事务后未使用(commit;)提交,所以事务未发生改变。

在B窗口提交后,在A窗口进行查询

存在问题:不可重复读 --- 同一事物内,最开始读到的数据和事务结束前任意时刻读到的数据不一致。

可重复读演示

<1> 关闭A,B的自动提交机制,使用可重复读隔离级别,开启事务



<2> 修改数据进行查询

B:update users set username='oupeng1234' where id=1; --- 修改id=1的username为oupeng1234
A:select * from users where id=1; --- 在A窗口查询id=1的数据



​​​​​​id=1的username未发生改变

B窗口提交后继续查看,依旧未改变

A窗口使用(commit;)提交,查询数据改变情况

存在问题:可重复读可能产生幻读问题,幻读问题很少出现。

可重复读的实现机制:MVCC --- 多版本并发控制,类似于乐观锁的实现机制

多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。

幻读演示(可重复读环境下)

事务T1:

事务T2:

只要 T1 和 T2 时刻执行产生的结果集是不相同的,那就发生了幻读的问题,比如:

  • T1 时间执行的结果是有 5 条行记录,而 T2 时间执行的结果是有 6 条行记录,那就发生了幻读的问题。

  • T1 时间执行的结果是有 5 条行记录,而 T2 时间执行的结果是有 4 条行记录,也是发生了幻读的问题。

由此,可把幻读理解为:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。

(3)mysql 幻读问题

MVCC + gap Lock

幻读是指在一个事务中,由于其他事务的并发操作,导致同一个查询在不同时间点返回不同的结果集。简单来说,幻读就是一个事务在读取数据的过程中,发现了一些“幻影”数据,这些数据在事务开始时不存在,但在事务结束时却突然出现了

两种解决方案

<1> 针对快照读(普通select语句):通过 MVCC 方式解决了幻读。MVCC 是一种在并发事务执行过程中管理数据版本的机制。它通过为每个事务分配唯一的事务 ID 和版本号来跟踪数据的变化。

<2> 针对当前读(select ... for update 等语句):是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(一)TinyWebServer的环境配置与运行

Linux下C轻量级Web服务器&#xff0c;项目来源于&#xff1a;TinyWebServer 配置环境&#xff08;为下载代码&#xff0c;编译运行做准备&#xff09; 1. 安装VMware VMware官网 选择产品&#xff0c;点击Workstation Pro 下载试用版&#xff08;注&#xff1a;需要在官网注册…

Java自学(三)面向对象编程

目录 什么是面向对象 举例 this关键字和构造器 实体类 电影小案例 什么是面向对象 我们日常生活中谈到一个事物&#xff0c;总会描述它的性质与行为&#xff0c;这个事物也就是 ”对象”。比如一个学生对象&#xff0c;他的属性有姓名、学号、成绩......他的行为有上课、…

【C++】C++模板进阶 —— 非类型模板参数、模板的特化以及模板的分离编译

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】C多…

史玉柱复出一年:巨人股权第三次被冻结,力推AI+游戏

大数据产业创新服务媒体 ——聚焦数据 改变商业 一则股权冻结信息&#xff0c;又一次将复出一年的史玉柱推上风口浪尖。 天眼查APP显示&#xff0c;巨人投资近日新增一则股权冻结信息&#xff0c;被执行人为史玉柱&#xff0c;冻结股权数额1.14亿元&#xff0c;冻结期限为三年…

Visual Studio 中将TAB设置为空格

将TAB设置为空格的原因很多&#xff0c;其中一点是为了统一不同编译器对TAB的解释&#xff0c;防止代码风格在不同编译器下不一致等。 在菜单中选择: 工具-->选项-->文本编辑器--->所有语言-->制表符 在窗口中选择&#xff0c;制表符大小和缩进大小都选为4&#xf…

【从入门到起飞】JavaSE—Stream流

&#x1f38a;专栏【JavaSE】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出我的问题 文章目录 &#x1f354;Stream流的作用&#x1f354;Stream流的使用步骤&#x1f384;获取Strea…

机器人过程自动化(RPA)入门 7. 处理用户事件和助手机器人

在UiPath中,有两种类型的Robot用于自动化任何流程。一个是后台机器人,它在后台工作。它独立工作,这意味着它不需要用户的输入或任何用户交互。另一个是前台机器人,也被称为助理机器人。 本章介绍前台机器人。在这里,我们将了解自动化过程中通过简单按键、单击鼠标等触发事…

代码随想录算法训练营第四十六天 | 动态规划 part 8 | 139.单词拆分、多重背包、背包问题总结

目录 139.单词拆分思路代码 多重背包背包问题总结 139.单词拆分 Leetcode 思路 dp[i] : 字符串长度为i的话&#xff0c;dp[i]为true&#xff0c;表示可以拆分为一个或多个在字典中出现的单词。如果确定dp[j] 是true&#xff0c;且 [j, i] 这个区间的子串出现在字典里&#xf…

仿真数据检查器如何比较数据

可以定制仿真数据检查器比较过程&#xff0c;以多种方式满足您的需求。在比较各运行时&#xff0c;仿真数据检查器会执行以下操作&#xff1a; 根据对齐设置&#xff0c;对齐基线运行和比较项运行中的信号对组。 仿真数据检查器不会比较无法对齐的信号。 根据指定的同步方法同…

Leetcode 剑指 Offer II 046. 二叉树的右视图

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底…

【中秋国庆不断更】OpenHarmony定义可动画属性:@AnimatableExtend装饰器

AnimatableExtend装饰器用于自定义可动画的属性方法&#xff0c;在这个属性方法中修改组件不可动画的属性。在动画执行过程时&#xff0c;通过逐帧回调函数修改不可动画属性值&#xff0c;让不可动画属性也能实现动画效果。 可动画属性&#xff1a;如果一个属性方法在animation…

批量剪辑视频软件,支持免费试用,合成视频,预览不限量不收费

几乎对于所有的短视频创作者来说&#xff0c;批量剪辑软件都是现在或者将来必备的办公软件。现如今市场上的批量剪辑软件也是层出不穷&#xff0c;质量也是良莠不齐。 今天给大家实实在在的推荐一款性价比非常高的批量剪辑软件——超级编导&#xff0c;适用于既想提升团队视频…

volatile关键字以及使用场景

在多线程环境下&#xff0c;如果编程不当&#xff0c;可能会出现程序运行结果混乱的问题。 出现这个原因主要是&#xff0c;JMM 中主内存和线程工作内存的数据不一致&#xff0c;以及多个线程执行时无序&#xff0c;共同导致的结果。 同时也提到引入synchronized同步锁&#x…

Android Studio插件版本与Gradle 版本对应关系

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、Gradle各版本对应关系3.1 Gradle 版…

杀掉进程但是fastapi程序还在运行

两个脚本&#xff0c;一个运行fastapi服务&#xff0c;一个重启服务&#xff1a; 启动服务先&#xff1a; 发现问题&#xff0c;杀掉 server.sh 后&#xff0c;依旧有&#xff1a; 不知道为什么会出现这个&#xff0c;直接kill吧&#xff1a; server.sh: #!/bin/bashparpath/…

Unity/WebGL打包/跨域问题/简单解决“......has been blocked by CORS policy: ......“

报错原文&#xff1a; Access to XMLHttpRequest atfile:///C:/Users/13171/My%20project%20(1)/Test/Build/test.data.gz from origin null has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-e…

NX 1988 如何将组件转为部件

打开组件 文件-导出-部件 指定部件名为1206&#xff0c;类选择&#xff1a;所有要导出的部件 选择完全加载 完成

(vue3)create-vue 组合式APIsetup、ref、watch,通信

优势&#xff1a; 更易维护&#xff1a;组合式api&#xff0c;更好的TS支持 之前是选项式api&#xff0c;现在是组合式&#xff0c;把同功能的api集合式管理 复用功能封装成一整个函数 更快的速度 更小的体积 更优的数据响应式&#xff1a;Proxy create-vue 新的脚手架工…

vue前端项目中添加独立的静态资源

如果想要在vue项目中放一些独立的静态资源&#xff0c;比如html文件或者用于下载的业务模板或其他文件等&#xff0c;需要在vue打包的时候指定一下静态资源的位置和打包后的目标位置。 使用的是 copy-webpack-plugin 插件&#xff0c;如果没有安装则需要先安装一下&#xff0c;…

Pikachu靶场——PHP反序列化漏洞

文章目录 1. PHP反序列化1.1 反序列化代码审计1.2 漏洞防御 1. PHP反序列化 可参考我写的另一篇博客&#xff1a;反序列化漏洞及漏洞复现。 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串&#xff0c;比如下面是一个对象&#xff1a; class S{publi…