事务,是指一个操作序列,这些操作要么都执行,或者都不执行,而且这一序列是无法分隔的独立操作单位。也就是符合原子性(Atomicity)、 一致性(Consistency)、 隔离性(Isolation)和持久性(Durability)的一组操作。
其中一致性是事务实现的目标,其他特性相当于是为了保证事务一致性的手段,比如原子性是保证事务执行操作不存在中间过程,无法分隔,保证事务的一致性;隔离性指在并发时防止事务之间相互干预影响,确保最后事务执行前后的一致性;持久性是哪怕系统崩溃出现故障时,数据修改也永远保存在数据库中,也确保了事务执行前后的一致性。
上面说到事务的隔离性,就是为了防止在并发时事务之间相互影响,那么如果没有事务之间的隔离,会发生哪些现象呢?
一个事务的撤销操作覆盖了另一个事务已提交的更新数据,比如有两个事务对统一账户进行操作,如下图所示:
在T3时刻两个事务都完成了取走200的操作,在T4时刻事务A提交余额,但是在T5时刻事务B撤销事务,如果没有隔离,那么会发生账户金额不变,却取走200的事情发生。
脏读指的是一个事务读取到另一个事务未提交的数据,如下图所示:
在T3时刻事务A取走200,但是在事务A提交撤销前,事务B在T4时刻对账户进行查询操作会读取到错误的信息。比如某人从账户中取出200,没有提交不想取了,提交撤销命令,如果这个时候在提交前有另一事务对该账户进行查询,会发现账户没取到钱却少200。
虚读其实也是一种不可重复读的现象,是指一个事务读到了另一个事务已经提交的新增数据,重点是新增或者删除,读取前后数据量不一致。如图:
比如事务A在新增数据后提交,在T2、T5时刻事务B的两次查询就会不一样,好像发生了幻觉一样。这就是幻读,发生了不存在的事情
一个事务读取到了另一个事务已经提交的更新数据,重点是修改,读取前后数据量一致,内容不一致。如图:
事务B在两次查询中发现数据库结果不一样
幻读和不可重复读的区别?
幻读重点是操作的新增或删除,不可重复读的重点是操作的修改。在读取上两者类似
但是在隔离控制上,针对于两种情况,对于不可重复读,只需要锁住满足条件的记录(如出现内部不一致的哪一行数据即可);对于幻读,因为出现了数据量不一致,不仅需要所著满足条件的记录,甚至于要锁住相近的记录或者(多行数据或者整个表)
一个事务可以读到另一个事务未提交的数据
一个事务可以读到另一个事务提交到的数据
一个事务中相同的查询会看到同样的数据行,也就是事务在执行期间看到的数据前后必须是一致的。是MySQL默认的隔离级别
事务之间以一种串行的方式执行,安全性非常高
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 否 | 否 | 否 |
读已提交 | 是 | 否 | 否 |
可重复读 | 是 | 是 | 否 |
串行化 | 是 | 是 | 是 |
关系型数据库一般遵循三范式设计思想
要求对属性的原子性,也就是数据库中的字段要具备原子性,不能再被拆分。
在满足第一范式的前提下,要保证数据表中的实例或行必须可以被唯一区分。
在满足第一、二范式的前提下,保证数据表中的所有非主键字段必须直接依赖主键,每个表中不包含其他表中已经包含的非主键关键字段的信息。
数据库索引是数据库管理系统中的一个排序的数据结构,用于协助快速查询、更新数据库表中的数据。通常使用B树或B+树来实现
是大多数MySQL存储引擎的默认索引类型,而且因为B+树的有序性,除了用于查找,还可以用于排序和分组,同时可以指定多个列作为索引列,多个索引列共同组成键。
InnoDB 的 B+ 树索引分为主索引和辅助索引。主索引的叶子节点data 域记录着完整的数据记录,一个表只能有一个聚簇索引。辅助索引的叶子节点的data域记录着主键的值,在使用辅助索引进行查找时,需要先查到主键值,然后再到主索引中进行查找。
能以O(1)时间进行查找,但是失去了有序性,只能支持精确查找,无法用于排序和分组
MyISAM 存储索引支持全文索引,用于查找文本中的关键词,不是直接比较是否相等
MyISAM存储引擎支持空间数据索引,可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询
在选择数据库引擎时要从实际业务出发,比如是否需要支持事务、外键、持久化等等。
InnoDB 是MySQL 5.5.5后的默认数据引擎,优点是支持事务和四种隔离级别,此外还支持外键、崩溃后的快速回复、支持全文检索、集群索引以及地理位置类型的存储和索引等功能。在MySQL8.0前重启服务InnoDB自增索引会丢失,无法自增。MyISAM引擎可以自增ID
它是 MyISAM 原生引擎,不支持事务功能,有独立的索引文件,对比InnoDB不支持外键
非关系型数据库(NoSQL)不同于传统的关系型数据库,通常用于超大规模数据的存储,因为这些数据存储不需要固定的模式,无需多余操作就可以横向扩展。
在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer’s theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
BASE:Basically Available, Soft-state, Eventually Consistent。 由 Eric Brewer 定义。
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
BASE是NoSQL数据库通常对可用性及一致性的弱要求原则:
ACID | BASE |
---|---|
原子性(Atomicity) | 基本可用(Basically Available) |
一致性(Consistency) | 软状态/柔性事务(Soft state) |
隔离性(Isolation) | 最终一致性 (Eventual consistency) |
持久性 (Durable) |
类型 | 部分代表 | 特点 |
---|---|---|
列存储 | Hbase Cassandra Hypertable | 顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。 |
文档存储 | MongoDB CouchDB | 文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能。 |
key-value存储 | Tokyo Cabinet / TyrantBerkeley DB MemcacheDB Redis | 可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能) |
图存储 | Neo4J FlockDB | 图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。 |
对象存储 | db4o Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。 |
xml数据库 | Berkeley DB XML BaseX | 高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath。 |
全文搜索数据库 | ElasticSearch solr | 它们的出现解决了关系型数据库全文搜索功能较弱的问题 |
文档型数据库通常以 JSON 或者 XML 为格式进行数据存储,主要以 MongoDB 和 Apache CouchDB 为代表。适用于敏捷开发、日志系统和社交系统等
MongoDB 是由 C++ 语言编写的基于分布式文件存储的开源数据库系统。在高负载的情况下,能添加更多的节点,可以保证服务器性能。MongoDB 将数据存储为一个文档,数据结构由键值(key => value)对组成。MongDB 文档类似于 JSON 对象。字段值可以包含其他文档,数据以及文档数组。其结构类似如下:
{
id: 123,
name: "wang",
sex: "male",
group: [ "news", "sports" ]
}
MongoDB 是以 JSON 格式存储数据,它对 JSON 做了一些优化能支持更多的数据类型,称为 BSON 。BSON 具有三个特点: 轻量、可遍历以及高效, 他的缺点是空间利用率不是很高。但是它拥有比关系型数据库更快的开发速度。
MongoDB 在 4.0 前是不支持事务,在 4.2 中实现了分布式事务的功能。
传统的关系型数据库主要依赖索引来实现快速查询功能,但是在全文搜索的业务下,索引很难满足查询的需求。关系型数据库的模糊匹配在数据量较大的情况下查询的效率是很低的。需要创建大量的索引,因此也需要专门的全文搜索引擎及相关的数据库来实现
键值型数据库通常被当作非持久化的内存型数据库缓存来使用,典型代表数据库是 Redis 和 Memcached 。此类数据的优点是性能比较高,但是对事务的支持不是很好。
见