数据库的读一致性分析

前言

提起数据库的事务,我们就会想到ACID特性:

A:Atomicity 原子性    事务中包含的各种操作,要么一起成功,要么全部失败

C:Consistency 一致性  事务从一个一致性的状态转变成另一个一致性的状态

I:Isolation 隔离性   各个事务之间的可见程度

D:Durability 持久性  数据库中的数据的改变应该是可以持久存储的

本篇博客将以MySQL为例分析数据库的读一致性。想分析清楚一致性,必先了解隔离级别。

数据库的隔离级别


在SQL标准中是定义了几种隔离级别的:

RU:Read Uncommitted(读取未提交内容)

RC:Read Committed(读取提交内容)

RR:Repeatable Read(可重读)

Serializable(可串行化)

Serializable这种隔离级别最高,若几个事务对同一份数据进行操作(即便是查询操作),它也针对每一个事务进行排序,严格按照排序进行事务的执行,显然解决了事务可能存在的冲突,但是会导致大量的超时以及锁竞争,因此在实际中大多是不会采用此种隔离级别的。

Oracle默认的隔离级别是:RC,并且Oracle只支持RC和Serializable这2种级别。RC,简单一句话,就是一个事务中只能看到另一个事务已经提交的数据的改变。那么RC会带来什么问题呢?在同一事务中,同一条SELECT语句可能会返回不一样的结果,即会产生  不可重复读。

MySQL默认的隔离级别是:RR。在该隔离级别下,可以保证在同一事务中,获取到的数据一致。这就是所谓的MySQL的读一致性,它的实现基于MVCC,后文中会分析。

RU可以让所有事务都读取到其他事务未提交的数据,会带来 脏读,同Serializable一样,在实际中,应用较少。

浅析MySQL MVCC原理


MVCC(MultiVersion Concurrency Control )多版本并发控制,可以简单的理解成为一个row lock的一个变种,只是在必要的时候加行锁。MySQL InnoDB的MVCC简单来讲是通过给表添加两列隐藏列来是实现的。一列是insert/update的时间,另一列是delete的时间,当然这里的时间并不是真正的时间,而是指SVN,即System Version Number,系统版本号,就是一个数字。每次开启一个事务,那么SVN号递增。

现在讨论在REPEATABLE READ下的MVCC实现:

SELECT

  • Innodb查找insert/update SVN小于等于当前事务的SVN的行,如果是小于,说明行之前就已经存在,如果是等于,说明这行是事务本身修改过的。
  • 行的删除时间列要么为空(说明该行未被删除)要么删除时间列的SVN大于当前事物的SVN(表示行是在事物开始之后被删除的)。

只有记录满足以上两条,才会被select语句返回!

这就是为何MYSQL在RR级别下,一个事务中是肯定读取不到“之后建立的”别的事务提交的数据,但是在本事务中更新的数据,可以读取出来的缘故!

INSERT

  • 插入之后以当前事务的SVN号更新创建列

DELETE

  • 删除之后,用当前SVN更新删除列

UPDATE

  • 更新创建列为当前SVN,同时更新删除列为update之前的创建列的SVN值

这样设计的优点是大部分的读操作都不用加锁了,而且是非阻塞的读取操作,使数据库操作简单,性能好,不足之处是增加了存储开销,需要额外的维护工作。

还是那句老话,用空间换取时间!

时间: 2024-08-11 16:38:41

数据库的读一致性分析的相关文章

由读一致性分析undo

下面通过undo的一致性读分析undo: [[email protected] ~]$ lsb_release -a LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch Distributor ID: EnterpriseEnterpriseServer Description:    Enterprise Linux Enterprise Linux Server releas

事务的特性、事务并发、事务读一致性问题

1 什么是数据库的事务? 1.1 事务的典型场景 在项目里面,什么地方会开启事务,或者配置了事务?无论是在方法上加注解,还 是配置切面 <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" rollback-for="Throwable"

数据库中的读一致性和脚本匹配

如果你想在函数中运行查询,而这个函数又要在SQL中调用,这时我们需要小心读一致性的问题了.如果这些函数要在一个运行时间很长的查询或者事务中调用,我们可能需要使用下面的命令在当前事务的SQL语句间强制保持读一致性  SET TRANSACTION READ ONLY sql数据库中的匹配1. "_"匹配任何单个字符2. "%"匹配任意数目字符(包括零个字符)3.  "*"匹配0个或多个在它前面的字符4. "[]"匹配在方括号中的

关系型数据库的隔离级别 读一致性

来自网络: 三种可防止的现象: 脏读(dirty read):事务可以读取其他事务还没有提交的修改: 不可重复读(nonrepeatable read):事务读取先前曾读取过的数据,发现其他的已提交事务修改或删除了要读取的数据: 幻象读(phantom read):事务再次执行一个查询,发现其他已提交事务插入了新的满足当前查询条件的数据. 针对以上三种现象,SQL92标准指定了4种隔离制度,这4种隔离制度一种比一种严格. Read uncommitted:允许脏读.不可重复读和幻象读: Read

深入解读阿里云数据库POLARDB核心功能会话读一致性

POLARDB架构 我们知道,POLARDB是一个由多个节点构成的数据库集群,一个主节点,多个读节点.对外默认提供两个地址,一个是集群地址,一个是主地址,推荐使用集群地址,因为它具备读写分离功能可以把所有节点的资源整合到一起对外提供服务. MySQL读写分离解决和引入的问题 用过MySQL的都知道,MySQL的主从复制简单易用,非常流行,通过把主库的Binlog异步地传输到备库并实时应用,一方面可以实现高可用,另一方面备库也可以提供查询,来减轻对主库的压力. 虽然备库可以提供查询,但存在两个问题

oracle如何保证读一致性

oracle保证读一致性原理 1:undo segment的概念 当数据库进行修改的时候,需要把保存到以前的old的数据保存到一个地方,然后进行修改,用于保存old数据的segment 就是undo segment. 以前老的东西是可以被覆盖掉的,因为undo segment是一种循环利用的方式. 看下图 如上图所示: 当oracle开启一个事务对table表中的数据进行修改,修改的那个数据(行数据)会被拷贝到 右图 undo  segment(用圆形表示是因为表示会被覆盖)中,这个时候事务没有

[翻译自mos文章]不完全恢复之后,open resetlogs之前,怎么快速的检查数据库是否处于一致性的状态?

不完全恢复之后,open resetlogs之前,怎么快速的检查数据库是否处于一致性的状态? 翻译自: How to quickly check that Database is consistent after incomplete recovery (Point in Time Recovery) before OPEN RESETLOGS (Doc ID 1354256.1) 适用于: Oracle Database - Enterprise Edition - Version 9.0.1

mysql数据库show processlist结果分析

下面我们一起来看看关于mysql数据库show processlist结果分析,希望此文章对各位同学会有所帮助. mysql> show processlist; +-–+-----+------–+ | Id | User | Host | db | Command | Time| State | Info +-–+-----+------–+ |207|root |192.168.0.2:51621 |mytest | Sleep | 5 | | NULL |208|root |192.16

探讨SELECT语句的元数据&amp;amp;动态取样&amp;amp;读一致性导致的一致性读和递归操作

前几天,论坛上的同行在讨论SELECT语句的元数据,动态取样和读一致性导致的一致性读和递归问题,今天有时间,就试着进行了测试,本人测试环境如下: win7_64+Oracle11.2.0.4_64 那么,下面就说下测试过程: 1.元数据:当用户向数据库发出SELECT语句后,在解析和执行过程中,肯定是需要读取SELECT相关的元数据,这样,SELECT的统计数据中就会包含递归操作,做这个测试的前提是要把其他因素排除掉(动态取样,一致性读): session1: session2: 由上可见,在表