mysql事务&&锁机制&&MVCC

1、事务的四大特性?

原子性、隔离性、持久性、一致性

原子性:当前事务的操作要么同时成功,要么同时失败。原子性由undo log来保证,undo log记录着数据修改前的信息,比如我们执行了一条insert语句,undo log 会记录一条对应的delete日志,执行了一条update操作,undo log会记录之前的旧值的update日志(在undo log中有当前行的拷贝副本);

在undo log中有当前行的拷贝副本

隔离性:在事务‘并发’执行时,他们内部的操作不能互相干扰; 如果多个事务可以同一时间操作同一份数据,会导致一系列的问题:脏读、幻读、不可重复读。 为了解决这几个问题,mysql定义了四种隔离级别供我们使用,分别是,读未提交、读已提交、可重复度、串行化。 隔离性是由各种锁来实现的,只是mysql屏蔽了各种锁的实现细节。

持久化:数据保存到磁盘上。 持久化由redo log来保证,当我们要修改数据时,mysql先把这条记录所对应的页找到,加载到内存上,将对应记录进行修改,因为数据加载到内存上,为了防止内存 修改完之后,MySQL就挂掉了,导致数据的丢失,mysql引进了redo log。每次修改完内存后,就写一份redo log,记录在某个页上做了什么修改,这样就算mysql在中途挂了, 我们也可以通过redo log对数据进行恢复。 redo log是顺序写的,因此写入数据很快(也就是在一个文件的末尾不断追加日志,这就是磁盘顺序写); 而且它记录的是物理修改(也就是xx页做了xx修改),因此文件的体积很小,恢复速度也很快;

也就是xx页做了xx修改

一致性:一致性可以理解为我们使用事务的‘目的’,原子性,隔离性,持久性都是为了确保一致性的手段,保证一致性需要有应用程序代码来保证。比如事务的回滚。

原子性由undo log来保证,记录当前行的拷贝副本,有旧记录,文件大,每次追加都是追加到头部(链表结构)?

持久性由redo log来保证,记录在哪里做了什么操作,文件小 。为了节省磁盘空间,InnoDB有专门的purge线程来清理undo log (https://blog.csdn.net/weixin_53184798/article/details/112309281)

2、mysql锁相关知识

在Innodb引擎中,根据锁的粒度,可以分为行锁和表锁。行锁实际上是作用于索引上的,当我们的SQL命中了索引,那么锁住的就是命中条件中的索引节点, 如果没有命中索引,那么锁住的就是整个索引树(表锁); 归纳:表锁还是行锁,完全取决于SQL条件是否有命中到对应的索引节点。 行锁又分为读锁和写锁,读锁是共享的,但是不允许其他事务update,写锁是排他的,会阻塞其他事务的读和写。

3、MVCC(多版本并发控制)

          上面我们谈到了事务的各种隔离级别,读未提交,读已提交,不可重复读,串行化。 在read uncommited级别下,读操作,是不加任何锁的,写操作会加排它锁(数据库是不可能允许在同一时间,更新同一条记录的!生产中是肯定不允许出现脏读的!) 但是加了排它锁,会阻塞其他事务的读和写,实际上就是当更新数据的时候,就没办法读写了,这样就极大的降低了数据库的性能。

           在mysql InnoDB引擎层次,为了解决这个问题,引进了新的解决方案(解决加锁后性能问题),叫做MVCC(Multi-Version-Concurrency-Controller),多版本并发控制。 在MVCC下,解决了加锁后性能问题,而且不会出现脏读。那么MVCC是如何实现的呢?

           MVCC通过生成数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。(核心思想是为每一个写操作创建一个版本,然后不同的事务根据 时间戳读取不同的版本) 回到事务的隔离级别,对于read commited,它生成的就是语句级快照,对于repeatable read,它生成的就是事务级快照。 read commited在读取时候生成了一个“版本号”,当其他事务commit之后,才会读取最新的已commit的“版本号”数据。 (每次读取时候都是读取最新的“版本号”),解决了脏读问题,会出现幻读和不可重复读问题,比如另一个事务delete,update了数据; repeatable read 每次读取数据的时候,读取的都是当前事务的“版本号”的数据,解决了幻读和不可重复读问题;(读的是历史版本的数据) serializable(串行化),相当于不允许事务的并发,最安全效率也最低,sychronized

4、MVCC原理 【MySQL笔记】正确的理解MySQL的MVCC及实现原理_SnailMann的博客-CSDN博客_mysql的mvcc

主要是通过undo log和read view 还有三个隐含字段(每个行里面的,当前事务ID,指向undo log中该条记录上一个版本的字段,隐含自增主键)来实现,redo log记录数据修改前的信息 查询出来的每一行记录,都会用readview来判断一下当前这行是否可以被当前事务看到,如果可以,则输出, 否则就利用undolog来构建历史版本,再进行判断,直到记录构建到最老的版本或者可见性条件满足。 原理有点复杂了,头疼,不看了

read commit每次都获取一个新的read view,repeatable view每次事务只获取一个read view;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值