mysql引擎机制_Mysql存储引擎以及锁机制

2023-11-19

一、常用命令

1、查看引擎(默认为InnoDB)

查看mysql提供的存储引擎:show engienes

查看mysql当前默认的存储引擎:show variables like '%storage_engine%'

查看某张表用了什么引擎:show create table 表名

2、修改引擎

修改表的存储引擎:alter table 表名 engine = 存储引擎

二、mysql存储引擎

1、mysql所支持的存储引擎

abb5dc264e77bec5a3cbe8bc4f62203d.png

2、四种常用的存储引擎

如果要提供提交、回滚、崩溃恢复能力的事物安全(ACID兼容)能力,并要求实现并发控制,InnoDB是一个好的选择

如果数据表主要用来插入和查询记录,MyISAM拥有较高的插入、查询速度,则MyISAM引擎能提供较高的处理效率

如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎作为临时表,存放查询的中间结果

如果只有INSERT和SELECT操作,可以选择Archive,Archive支持高并发的插入操作,但是本身不是事务安全的。Archive非常适合存储归档数据,如记录日志信息可以使用Archive

使用哪一种引擎需要灵活选择,一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求,使用合适的存储引擎,将会提高整个数据库的性能

三、MyISAM与InnoDB区别

1、构成上的区别(底层实现)

MyISAM(B+树):每个MyISAM在磁盘上存储成三个文件。每个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD(MYData)。索引文件的扩展名是.MYI(MYIndex)。

InnoDB(B树):基于磁盘的资源是InnoDB表空间数据文件和它的日志文件,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。

2、auto_increment

(对于AUTO_INCREMENT类型的字段,InnoDB中必须单独建索引,而在MyISAM中可以和其他字段一起建立联合索引。)

innodb引擎下自增id

innodb引擎下,如果显示insert了最大值,那么下次的AUTO_INCREMENT值就是这个最大值+1

如果这时候再把其中一个id值update成105,那么下次的AUTO_INCREMENT却还是不变

如果这时再利用自增段去插入,到了105的时候是会报错的

这时继续插入,不会报错,因为刚才即使报错了,AUTO_INCREMENT值依旧会增加

重启mysql服务后,AUTO_INCREMENT变为1

Myisam引擎下自增id

myisam引擎下,如果显示insert了最大值,那么下次的AUTO_INCREMENT值就是这个最大值+1

如果这时候再把其中一个id值update成105,那么下次的AUTO_INCREMENT就会变成106(这和innodb是不同的!)

当db重启后,myisam引擎的AUTO_INCREMENT值不变

3、事物处理

MyISAM类型支持的表强调的是性能,其执行的速度比InnoDB类型更快,但是不提供事务支持

InnoDB提供事物支持,外部键等高级数据库功能

4、锁机制

在执行数据库写入操作(insert、update、delete)的时候,

MyISAM会锁表,

而Innodb默认会锁行,但也会出现锁表的情况

5、读取行数

没有where的SELECT COUNT(*):MyISAM始终保留一张表的行数,因此这条语句几乎瞬间就可以执行完,而Innodb会一行行的累加,要扫描一张表来计算有多少行

四、mysql锁机制

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

1、基本锁类型

锁包括行级锁和表级锁

行级锁:开销大,加锁慢;会出现死锁;锁定力度最小,发生锁冲突的概率最低,并发度也最高

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低

2、MyISAM表锁

MySQL表级锁有两种模式:表共享锁(Table Read Lock)和表独占写锁(Table Write Lock)。

对MyISAM的读操作,不会阻塞其他session对同一表请求,但会阻塞对同一表的写请求;

对MyISAM的写操作,则会阻塞其他session对同一表的读和写操作;

MyISAM表的读操作和写操作之间,以及写操作之间是串行的。

当一个线程获得对一个表的写锁后,只有持有锁线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。

加锁方式

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。

显式加锁

(1)表独占写锁(lock table A write)

获得表A的WRITE锁定

当前session对锁定表的查询、更新、插入操作都可以执行,其他session对锁定表的查询被阻塞,需要等待锁被释放,陷入等待状态

释放锁后,其他session获得锁,查询结果返回

(2)表共享读锁(lock table A read)

获得表A的READ锁定

当前session可以查询该表记录,其他session也可以查询该表的记录

当前session不能查询没有锁定的表,其他session可以查询或者更新未锁定的表

当前session插入或者更新锁定的表都会提示错误,其他session更新锁定表会等待获得锁,陷入等待状态

释放锁后,其他session获得锁,更新操作完成

并发插入(lock table A read local)

上面提到的MyISAM表的读和写是串行的,但那时就总体而言,在一定条件下,MyISAM表也支持查询与插入操作的并发进行

05cd59ec1bef7f2d538b1f83eddb9d6a.png

5d2086c34294fca9d72a6058c2cef9c2.png

MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。

0:不允许并发插入

1:没有空洞(即表的中间没有被删除的行),允许一个进程读表的同时,另一个进程从表尾插入记录(更新会等待),这也是默认设置,注意:空洞问题可以通过定期在系统空闲时段执行OPTIMIZE TABLE语句来整理空间碎片,回收因删除记录而产生的中间空洞

2:无论有没有空洞,都允许在表尾并发插入记录

例子:session1获得一个表的READ LOCAL锁,该session虽然可以对表进行查询操作,但不能对表进行更新操作;其他session虽然不能对表进行删除和更新操作,但可以对表进行并发插入操作,这里假设该表中间不存在空洞

MyISAM的锁调度问题

MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的。那么,一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得锁。不仅如此,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!这是因为MySQL认为写请求一般比读请求更重要。这也是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。我们可以通过一些设置来调节MyISAM的调度行为。

通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。

在my.cnf的配置方法[mysqld] low-priority-updates

通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低

通过指定INSERT UPDATE DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。

3、InnoDB行锁

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁,事务可以通过以下语句显示给记录集加共享锁或排他锁。

(1)共享锁(S):SELECT * FROM table_name WHERE ...LOCK IN SHARE

允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁

又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A。其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。

这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

set autocommit = 0(通过以上设置autocommit=0,则用户将一直处于某个事务中,直到执行一条commit提交或rollback语句才会结束当前事务重新开始一个新的事务。)

当前session对id = 10的记录加share mode的共享锁;其他session仍然可以查询记录,并也可以对该记录加share mode的共享锁

当前session对锁定的记录进行更新操作,等待锁;其他session也对该记录进行更新操作,则会导致死锁退出

当前session获得锁后,可以成功更新

(2)排他锁(X):SELECT * FROM table_name WHERE ...FOR UPDATE

允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁

又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A。其他事务不能再对A加任何锁,直到T释放A上的锁。

这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

set autocommit = 0

当前session对id = 10的记录加for update的排他锁;其他session可以查询该记录,但是不能对该记录加排他锁,会等待获得锁

当前session可以对锁定的记录进行更新操作,更新后释放锁

其他session获得锁,得到其他session提交的记录

(3)行锁的实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过检索条件检索数据,InnoDB才使用行级锁,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁,也就是使用表锁

(4)什么时候使用表锁

对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们选择InnoDB表的理由。但在个别特殊事务中,也可以考虑使用表锁

第一种情况:事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下一颗考虑使用表锁里提高事务的执行速度。

第二种情况:事务涉及多张表,比较复杂,很可能引起死锁,造成大量事务回滚。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁,减少数据库因事务回滚带来的开销。

当然,应用中的这两种事务不能太多,否则,就应该考虑使用MyISAM表了。

(5)关于死锁

所谓死锁,是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁

典型的死锁问题

9ad75e8eb5ba135eba150c83b1560b7c.png

两个事务都需要获得对方持有的排他锁才能继续完成事务,这种循环等待就是典型的死锁(都是for update排他锁, 一个事务select 表A id1,另一个事务select 表B id1,第一个事务又select 表B id1,第二个事务select 表A id1)

通常来说,死锁都是应用设计的问题,通过调整业务流程、数据库对象设计、事务大小、以及访问数据库的SQL语句,绝大多数死锁都可以避免。

解决办法:

在应用中,如果不同的程序会并发存取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会。

由于两个session访问两个表的顺序不同,发生死锁的机会就非常高!但如果以相同的顺序来访问,死锁就可以避免

在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应该先申请共享锁,更新时再申请排他锁,因为当用户申请排他锁时,其他事务可能又已经获得了相同记录的共享锁,从而造成锁冲突,甚至死锁

一个事务申请了共享锁之后无法再申请排他锁(也就是保证事务T在查询操作加了共享锁之后无法执行修改)

在REPEATABLE-READ隔离级别下,如果两个线程同时对相同条件记录用SELECT ... FOR UPDATE加排他锁,在没有符合该条件记录的情况下,两个线程都会加锁成功。程序发现记录尚不存在,就视图插入一条新记录,如果两个线程都这么做,就会出现死锁。这种情况下,将隔离级别改成READ COMMITTEND,就可避免问题

改进措施

尽量使用较低的隔离级别;

精心设计索引,并尽量使用索引访问数据,使加锁更精确,从而减少锁冲突的机会;

选择合理的事务大小,小事务发生锁冲突的几率也更小

给记录集显式加锁时,最好一次性请求足够级别的锁,比如要修改数据,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁

不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行,这样可以大大减少死锁的机会

对于一些特定的事务,可以使用表锁来提高处理速度或减少发生死锁的几率。

在了解InnoDB锁特性后,用户可以通过设计和SQL调整等措施减少锁冲突和死锁,包括以下一项

如果出现死锁,可以用SHOW INNODB STATUS 命令来确定最后一个死锁产生的原因。返回结果包括死锁相关事务的详细信息,如引发死锁的SQL语句,事务已经获得的锁,正在等待的锁,以及被回滚的事务

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mysql引擎机制_Mysql存储引擎以及锁机制 的相关文章

随机推荐

  • json.decoder.JSONDecodeError: Invalid control character at: line 1 column 3,python中str与json类型转换报错如何解

    使用json转 json数据保密 再此不展示 判断类型 print type str json json dump json loads str json 报错如下 json decoder JSONDecodeError Invalid
  • 【Data Mining】【第五章作业】

    文章目录 一 单选题 二 多选题 三 填空题 一 单选题 1 回归分析中使用的距离是点到直线的垂直坐标距离 最小二乘准则是指 A B C D 正确答案 D 2 回归分析的步骤为 进行相关分析 建立预测模型 确定变量 确定预测值 计算预测误差
  • yolov4训练自己的数据集

    YOLOv4训练自己的数据集 1 电脑配置 2 下载并配置 3 测试 4 训练 1 电脑配置 win10 OpenCV4 1 VS2019 cuda10 2 2 下载并配置 1 YOLOv4网址 https github com Alexe
  • aix升级openssh_AIX6.1上源码编译升级openssh6.6p1

    最近因为绿盟扫描到AIX5 3 AIX6 1系统有openssh高危漏洞 OPENSSH6 4之前的都报高危漏洞 IBM官网上也只有最新的openssh6 0安装文件供下载 没办法只有自己试验的用源码来安装升级 期间各种报错 搞了差不多一周
  • educoder答案pythonnumpy_Educoder 题解

    Solution 4 2 第一关 求个导发现有两个根 分别二分就行了 importnumpy as np E 1e 6 begin 请在此填写代码 计算6 np exp x 113 x 17 0的根 deff x return 6 np e
  • 语义分割实践—耕地提取(二分类)

    开篇 感谢李沐老师团队为深度学习教学做出的巨大贡献 对李沐老师及团队致以深深的敬意 同时 对技术开发社区以及编程技术网站的优质创作者们 Jack Cui等 表示深深的感谢 一 深度学习网络中的常见概念 一 Ground Truth 通常指人
  • 06 CubeMX HAL库stm32作从机 硬件I2C中断接收无BUG程序

    文章目录 CubeMX HAL库stm32作从机 硬件I2C中断接收无BUG程序 一 设置烧录模式 二 使用外部晶振 三 开启IIC中断 四 设置IIC参数 五 配置外部时钟 六 设置工程信息 七 代码生成项配置 八 在Keil中打开工程
  • on conflict do update

    使用ON CONFLICT DO UPDATE语法的主要优点是可以使SQL语句更加简洁和高效 相比于传统的INSERT和UPDATE两个步骤执行 使用ON CONFLICT DO UPDATE可以将这两个步骤合并为一个数据库操作 从而减少了
  • IntelliJ IDEA 15款 神级超级牛逼插件推荐(自用,真的超级牛逼)

    来源 http suo im 5X5Rql 满满的都是干货 所有插件都是在 ctrl alt s 里的plugins 里进行搜索安装 1 CodeGlance 代码迷你缩放图插件 2 Codota 代码提示工具 扫描你的代码后 根据你的敲击
  • android检测新版本并下载安装的方法

    很多客户端程序都有检测是否有更新的功能 本文大体介绍了其实现过程 此功能模块也是开源中国客户端中的源码 个人感觉用到的安卓基础知识还是比较全面的 很适合初学者学习进阶 检查App更新 param context param isShowMs
  • Win10 64bit系统中VS2015与OpenCV3.2配置开发环境

    1 将OpenCV解压到D盘根目录 个人认为纯英文目录比较保险 2 VS2015建立控制台工程 设置为64位debug开发环境 3 配置工程属性 在可执行目录 executable directories 中 确认已包含opencv包里的b
  • VRTK4.0 学习Day3

    假装是第三天吧 我这里的情况是 勾选了这个支持之后 会将下方这个XR Plug in Managerment就下好了 我还打开了那个保龄球的那个项目 那里面的这个XR Plug in Managerment是没有的 也不要去导入 我导入之后
  • windows下搭建编译chromium的开发环境

    本篇为windows下搭建编译chromium的方法 mac篇 mac下搭建编译chromium的开发环境 二七 CSDN博客 linux篇 linux 搭建和编译 chromium 环境 二七 CSDN博客 注意 搭建部署chromium
  • js 将一维数组转成二维数组

    开发时遇上一个将一维数组转换成二维数据结构的要求 记录一下工具函数 说明 这是一个函数 直接复制到
  • 接口测试这么玩才明白

    接口测试作为当下提升测试效能的利器 逐步被大家所认同 但同时很多团队在落地接口自动化时 又会感觉效果不是很明显 投入了大量的时间 写了很多脚本 但是效果并不是很明显 其中有各种问题 结合某团队的现状 分享一些实践经验 仅供参考 引入接口测试
  • Java解析XML的四种方法详解

    XML现在已经成为一种通用的数据交换格式 它的平台无关性 语言无关性 系统无关性 给数据集成与交互带来了极大的方便 对于XML本身的语法知识与技术细节 需要阅读相关的技术文献 这里面包括的内容有DOM Document Object Mod
  • c语言下列编程段的错误,C语言编程题目(有错误)

    问题描述 C语言编程题目 有错误 输入精度e 用下列公式求cosx的近似值 精确到最后一项的绝对值小雨e 要求调用和定义函数funcos e x 求余弦函数的近似值 cosx x的0次方 0 x的2次方 2 x的4次方 4 x的6次方 6
  • 58同城 -- 前端一面

    面我的是一个小哥哥 面试体验挺好的 大概进行了35分钟左右 自我介绍 面试内容 为什么向做前端 怎么学习的前端 本人非科班哈 然后问我项目 直接问项目 没问笔试令我有点意外 问我印象最深的项目 印象最深的功能 遇到的难点 前端存储的区别 C
  • python格式化字符串 时间戳 转 UTC(2023-01-11T16:00:00Z)格式时间

    前言 公司前端的时间参数分为两类 一种是时间戳传参 另一种是 2023 01 11T16 00 00Z UTC 时间传参 有些脚本需要用到datatime datatime因此要整理一下相关方法 获取时间戳 my timestamp tim
  • mysql引擎机制_Mysql存储引擎以及锁机制

    一 常用命令 1 查看引擎 默认为InnoDB 查看mysql提供的存储引擎 show engienes 查看mysql当前默认的存储引擎 show variables like storage engine 查看某张表用了什么引擎 sho