• mysql数据库4种事务的特性以及实现原理


    事务的四大特性(ACID):

    1.原子性(atomicity):一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。

    2.一致性(consistency):数据库总数从一个一致性的状态转换到另一个一致性的状态。

    3.隔离性(isolation):一个事务所做的修改在最终提交以前,对其他事务是不可见的。

    4.持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。

    ACID:

    • 原子性: 语句要么都执行,要么都不是执行,是事务最核心的特性,事务本身来说就是以原子性历来定义的,实现主要是基于undo log
    • 持久性: 保证事务提交之后,不会因为宕机等其他的原因而导致数据的丢失,主要是基于 redo log实现
    • 隔离性: 保证事务与事务之间的执行是相互隔离的,事务的执行不会受到其他事务的影响。InnoDB存储引擎默认的数据库隔离级别是 RR(可重复读) ,RR又主要是基于锁机制,数据的隐藏列,undo log类 以及 next-key lock机制
    • 一致性: 事务追求的最终目标,一致性的实现即需要数据库层面的保障,也需要应用层面的保障。

    数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read (默认)、Serializable 。

    脏读:一个事物看到另一个事物未提交的数据

    不可重复读:一个事物范围内,两次查询到的数据不一致(针对于update)。

    幻读:一个事物范围内,两次查询到的数据不一致(针对的是insert)。

    Read uncommitted:未提交读,啥也避免不了

    Read committed :读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题

    Repeatable read:可重复读,解决了不可重复读。

    Serializable:在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

    mysql数据库中的三种日志:redolog:保证的是数据的持久性,undolog:保证的是数据的隔离性以及原子性

    1、为何引入redolog ,redo log如何保证持久性?

    当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改写入日志,更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。

    2、既然redo log也需要在事务提交时将日志写入磁盘,为什么它比直接将Buffer Pool中修改的数据写入磁盘(即刷脏)要快呢?主要有以下两方面的原因:
    (1)刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。
    (2)刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redo log中只包含真正需要写入的部分,无效IO大大减少。

    3、redo log 与 binlog

    我们知道,在MySQL中还存在binlog(二进制日志)也可以记录写操作并用于数据的恢复,但二者是有着根本的不同的:

    (1)作用不同:redo log是用于crash recovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-time recovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。
    (2)层次不同:redo log是InnoDB存储引擎实现的,而binlog是MySQL的服务器层(可以参考文章前面对MySQL逻辑架构的介绍)实现的,同时支持InnoDB和其他存储引擎。
    (3)内容不同:redo log是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
    (4)写入时机不同:binlog在事务提交时写入;redo log的写入时机相对多元:

    • 前面曾提到:当事务提交时会调用fsync对redo log进行刷盘;这是默认情况下的策略,修innodb_flush_log_at_trx_commit参数可以改变该策略,但事务的持久性将无法保证。
    • 除了事务提交时,还有其他刷盘时机:如master thread每秒刷盘一次redo log等,这样的好处是不一定要等到commit时刷盘,commit速度大大加快。

    4、隔离性的探讨,主要可以分为两个方面:

    • (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
    • (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性

    5、锁机制:表锁和行锁

    锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

    行锁与表锁

    按照粒度,分为表锁与行锁:
    MyISAM 支持表锁,InnoDB 支持表锁和行级锁,默认是行级锁表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发送锁冲突的概率比较高,并发处理效果较低。行级锁: 开销大,加锁慢,会出现死锁,锁定粒度较小,发生锁冲突的概率会小一点,并发处理的效果高。

    6、MVCC

    前面讲到了 RR(可重复读)解决了 脏读,不可重复读,幻读等问题使用到的就是MVCC(Multi-Version Concurrency Control) 既多版本的并发控制:在同一个时刻,不同的事物读取到的数据可能是不同的(多版本)。对于MVCC来说最大的优点就是读不加锁,因此读写不冲突,并发性能好
    InnoDB实现MVCC,多个版本的数据可以共存,主要是依靠数据的隐藏列(也可以称之为标记位)和undo log。其中数据的隐藏列包括了该行数据的版本号、删除时间、指向undo log的指针等等;当读取数据时,MySQL可以通过隐藏列判断是否需要回滚并找到回滚需要的undo log,从而实现MVCC。

    7、

    如何解决幻读

    nnoDB实现的RR(可重复读)通过next-key lock机制避免了幻读现象。

    next-key lock是行锁的一种,实现相当于record lock(记录锁) + gap lock(间隙锁);其特点是不仅会锁住记录本身(record lock的功能),还会锁定一个范围(gap lock的功能)。当然,这里我们讨论的是不加锁读:此时的next-key lock并不是真的加锁,只是为读取的数据增加了标记(标记内容包括数据的版本号等);

  • 相关阅读:
    java保留字
    12个不可不知的Sublime Text应用技巧和诀窍
    人生准则
    基于Android 的蓝牙A2DP 功能的实现
    蓝牙协议栈详解
    我的2015计划
    今日学习
    滤波器介绍
    STLINK V2安装使用详解
    javascript闭包
  • 原文地址:https://www.cnblogs.com/sunny-miss/p/14871983.html
Copyright © 2020-2023  润新知