【Sql】MVCC有关问题,以及锁,日志和主从复制原理

这篇具有很好参考价值的文章主要介绍了【Sql】MVCC有关问题,以及锁,日志和主从复制原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Sql】MVCC有关问题,以及锁,日志和主从复制原理,sql,数据库

目录

MVCC

解决什么问题?

实现原理

隐式字段

undo log

Read View(读视图)

InnoDB 对 MVCC 的实现

分类

锁升级?

InnoDB 的行锁?

死锁避免?

乐观锁和悲观锁

日志

主从复制原理

主从复制的作用

MySQL主从复制解决的问题

涉及3个线程

复制过程

读写分离


MVCC

一种多版本并发控制机制,用处就是在多个并发事务同时读写数据库时保持数据的一致性和隔离性。它是通过在每个数据行上维护多个版本的数据来实现的。当一个事务要对数据库中的数据进行修改时,MVCC 会为该事务创建一个数据快照,而不是直接修改实际的数据行。

解决什么问题?

在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。同时还可以解决脏读、幻读、不可重复读等事务隔离问题,但不能解决更新丢失问题。

实现原理

它的实现原理主要是依赖记录中的 3 个隐式字段、undo log、Read View 来实现的。

通过保存数据在某个时间点的快照来实现的.不同存储引擎的MVCC实现是不同的,典型的有乐观并发控制和悲观并发控制

隐式字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段

  • DB_ROW_ID 6byte, 隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引

  • DB_TRX_ID 6byte, 最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID

  • DB_ROLL_PTR 7byte, 回滚指针,指向这条记录的上一个版本(存储于rollback segment里)

  • DELETED_BIT 1byte, 记录被更新或删除并不代表真的删除,而是删除flag变了

undo log

InnoDB把这些为了回滚而记录的这些东西称之为undo log。

注意,由于查询操作并不会修改任何用户记录,所以在查询操作执行时,并不需要记录相应的undo log。

undo log主要分为3种:

  • Insert undo log :插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉就好了。

  • Update undo log:修改一条记录时,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值就好了。

  • Delete undo log

    :删除一条记录时,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了。

    • 删除操作都只是设置一下老记录的DELETED_BIT,并不真正将过时的记录删除。

    • 为了节省磁盘空间,InnoDB有专门的purge线程来清理DELETED_BIT为true的记录。为了不影响MVCC的正常工作,purge线程自己也维护了一个read view(这个read view相当于系统中最老活跃事务的read view);如果某个记录的DELETED_BIT为true,并且DB_TRX_ID相对于purge线程的read view可见,那么这条记录一定是可以被安全清除的。

Read View(读视图)

定义:说白了Read View就是事务进行快照读操作的时候生产的读视图,在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)

InnoDB 对 MVCC 的实现

MVCC 的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB 通过数据行的 DB_TRX_IDRead View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改

分类

表级锁: MySQL 中锁定粒度最大的一种锁(全局锁除外),是针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。

行级锁: MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。

表锁和行锁都有共享锁和排它锁

  1. 共享锁:又称读锁,多个用户可以同一时刻读取同一个资源,相互之间没有影响。事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。不堵塞,

  2. 排它锁:又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。

意向锁是表级锁,共有两种:

  1. 意向共享锁:事务有意向对表中的某些记录加共享锁,加共享锁前必须先取得该表的意向共享锁。

  2. 意向排他锁:事务有意向对表中的某些记录加排他锁,加排他锁之前必须先取得该表的意向排他锁。

锁升级?
  • MySQL 行锁只能加在索引上,如果操作不走索引,就会升级为表锁。因为 InnoDB 的行锁是加在索引上的,如果不走索引,自然就没法使用行锁了,原因是 InnoDB 是将主键索引 和相关的行数据共同放在 B+ 树的叶节点。InnoDB 一定会有一个 主键,二级索引 查找的时候,也是通过找到对应的主键,再找对应的数据行。

  • 当非唯一索引上记录数超过一定数量时,行锁也会升级为表锁。测试发现当非唯一索引相同的内容不少于整个表记录的二分之一时会升级为表锁。因为当非唯一索引相同的内容达到整个记录的二分之一时,索引需要的性能比全文检索还要大,查询语句优化时会选择不走索引,造成索引失效,行锁自然就会升级为表锁。

InnoDB 的行锁?

InnoDB 行锁是通过对索引数据页上的记录加锁实现的,MySQL InnoDB 支持三种行锁定方式:

  • 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁。

  • 间隙锁(Gap Lock):锁定一个范围,不包括记录本身。

  • 临键锁(Next-Key Lock):Record Lock+Gap Lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题(MySQL 事务部分提到过)。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。

在 InnoDB 默认的隔离级别 REPEATABLE-READ 下,行锁默认使用的是 Next-Key Lock。但是,如果操作的索引是唯一索引或主键,InnoDB 会对 Next-Key Lock 进行优化,将其降级为 Record Lock,即仅锁住索引本身,而不是范围。

死锁避免?

定义:死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

  1. 设置获取锁的超时时间,至少能保证最差情况下,可以退出程序,不至于一直等待导致死锁;

  2. 设置按照同一顺序访问资源,类似于串行执行;

  3. 避免事务中的用户交叉;

  4. 保持事务简短并在一个批处理中;

  5. 使用低隔离级别;

乐观锁和悲观锁

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:一般会使用版本号机制或CAS算法实现。用在读多的场景。

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制。用在写多的场景。

日志

更新语句的流程会涉及到三种日志:

  • undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC

  • redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复

  • binlog (归档日志):是 Server 层生成的日志,主要用于数据备份和主从复制

写入原理:

主从复制原理

  • 主从复制:将主数据库中的DDL和DML操作通过二进制日志(BINLOG)传输到从数据库上,然后将这些日志重新执行(重做);从而使得从数据库的数据与主数据库保持一致。

  • 原理

    • 在主库上把数据更高记录到二进制日志

    • 从库将主库的日志复制到自己的中继日志

    • 从库读取中继日志的事件,将其重放到从库数据中

主从复制的作用
  1. 主数据库出现问题,可以切换到从数据库。

  2. 可以进行数据库层面的读写分离。

  3. 可以在从数据库上进行日常备份。

MySQL主从复制解决的问题
  • 数据分布:随意开始或停止复制,并在不同地理位置分布数据备份

  • 负载均衡:降低单个服务器的压力

  • 高可用和故障切换:帮助应用程序避免单点失败

  • 升级测试:可以用更高版本的MySQL作为从库

涉及3个线程
  • binlog 线程 : 负责将主服务器上的数据更改写入二进制日志中。

    I/O 线程 : 负责从主服务器上读取二进制日志,并写入从服务器的中继日志中。

    SQL 线程 : 负责读取中继日志并重放其中的 SQL 语句。

复制过程
  1. 主节点在每个事务更新数据完成之前,将该操作记录串行地写入到binlog文件中。

  2. 从节点开启一个I/O Thread,该线程在主节点打开一个普通连接,主要工作是二进制日志传输。如果读取的进度已经跟上了主节点,就进入睡眠状态并等待主节点产生新的事件。I/O线程最终的目的是将这些事件写入到中继日志中。

  3. SQL Thread会读取中继日志,并顺序执行该日志中的SQL事件,从而与主数据库中的数据保持一致。

读写分离

主服务器处理写操作以及实时性要求比较高的读操作,而从服务器处理读操作。

读写分离能提高性能的原因在于:

  • 主从服务器负责各自的读和写,极大程度缓解了锁的争用;

  • 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销;

  • 增加冗余,提高可用性。文章来源地址https://www.toymoban.com/news/detail-839813.html

到了这里,关于【Sql】MVCC有关问题,以及锁,日志和主从复制原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • mysql主从复制及原理

    主要基于MySQL二进制日志 主要包括三个线程(2个I/O线程,1个SQL线程) 1、MySQL将数据变化记录到二进制日志中; 2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中; 3、Slave将中继日志中的事件在做一次,将数据变化,反应到自身(Slave)的数据库 在主服务器(master)上启用

    2024年02月14日
    浏览(31)
  • 图解-Redis主从复制原理

    大家好,我是「云舒编程」,今天我们来Redis主从复制原理。 文章首发于微信公众号: 云舒编程 关注公众号获取: 1、大厂项目分享 2、各种技术原理分享 3、部门内推 主从复制是指用户可以搭建多个服务器,其中几个服务器当做主服务器,提供写功能。其余的服务器当做从

    2024年01月25日
    浏览(39)
  • MySQL主从复制原理及实验

       1.需要两台服务器,如我的分别是:         1.  -》 192.168.197.146---主库         2.  -》 192.168.197.147---从库 2.分别关闭防火墙或者放行mysql端口号3306         如: systemctl   stop  firewalld                 systemctl    disable  firewalld 1.在mysql的配置文件  /etc/my.cnf中添加:

    2024年02月16日
    浏览(32)
  • ​Redis主从复制模式原理及演进​

    主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。 默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能

    2023年04月15日
    浏览(38)
  • MySQL主从复制原理剖析与应用实践

    vivo 互联网服务器团队- Shang Yongxing MySQL Replication(主从复制)是指数据变化可以从一个MySQL Server被复制到另一个或多个MySQL Server上,通过复制的功能,可以在单点服务的基础上扩充数据库的高可用性、可扩展性等。 MySQL在生产环境中被广泛地应用,大量的应用和服务都对MyS

    2023年04月11日
    浏览(78)
  • SQL有关表的左连接,右连接,以及内连接

            首先我们需要想一下,我们为什么需要将表连接在一起呢?换种说法,即我们需要查询的数据不在同一张表里面,而是在A表中查出一部分,然后再去B表中查出一部分,然后两者结合在一起,才是我们需要的部分。那么我们为什么不是把我们需要的数据从A表中查出

    2024年02月11日
    浏览(51)
  • springboot项目外卖管理 day09-mysql主从复制以及nginx入门

    示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 目前我们所有的读和写的压力都是由一台数据库来承担, 如果数据库服务器磁盘损坏,则数据会丢失(没有备份) 解决这个问题,就可以用MySQL的主从复制,写操作交给主库,读操作交给从库

    2024年02月12日
    浏览(39)
  • 【征服Redis12】redis的主从复制问题

    从现在开始,我们来讨论redis集群的问题,在前面我们介绍了RDB和AOF两种同步机制,那你是否考虑过这两个机制有什么用呢?其中的一个重要作用就是为了集群同步设计的。 Redis是一个高性能的键值存储系统,广泛应用于Web应用、缓存、消息队列等领域。在实际应用中,为了

    2024年01月21日
    浏览(35)
  • MySQL高级第十七篇:数据库主从复制原理及保证数据一致性

    在实际工作中,我们常常将Redis作为缓存与MySQL来配合使用,当有请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在再访问数据库。 这样就提升了读取的效率,也减少了对后端数据库的访问压力。 此外,对于一般数据库应用而言,都是 读多写少 的,

    2023年04月25日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包