加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

当数据库遇到分布式,你会怎么做?

发布时间:2020-03-10 17:11:38 所属栏目:MySql教程 来源:站长网
导读:副标题#e# 数据库通常有着完善的事务支持,但是局限于单机的存储和性能,于是就出现了各种分布式解决方案。最近读了《Designing Data-Intensive Applications》这本书,所以做一个总结,供大家做个参考,有什么不对的请大家指正,一起讨论。 数据模型 数据

保存一系列在后台合并的SSTables,即使数据集比可用内存大得多,仍能继续工作。由于数据按序存储,因此可以高效地执行范围查询(扫描所有高于某些最小值和最高值的所有键),并且磁盘写入时连续的,所以可以支持非常高的写入吞吐量。

事务

在数据库系统中,会遇到各种问题:

数据库软件、硬件可能在任意时刻故障(包括写操作进行一半时)

应用程序任何时刻都可能崩溃(包括一系列操作的中间)

网络中断会切断应用与数据库的连接,或数据库之间的连接

多个应用可能会同时写入数据库,覆盖彼此的修改

应用可能会读取到无意义的数据,因为数据只更新了一部分

应用质检的竞争条件可能导致各种非预期结果

事务一直是简化这些问题的首选机制。事务是应用程序将多个读写操作组合成一个逻辑单元的一种方式。从概念上讲,事务中的所有读写操作被视为单个操作来执行:整个事务要么成功,要么失败后回滚。如果失败,应用可以安全地重试。对于事务来说,应用的错误处理简单多了,不用担心部分失败的情况了。

事务提供的安全保障,由ACID来描述。即原子性Atomicity,一致性Consistency,隔离性Isolation,持久性Durability,旨在为数据库中的容错性建立精确的术语。

单对象 vs 多对象

事务通常被理解为,将对多个对象上的多个操作合并为一个执行单元的机制。但许多分布式数据库只提供了单对象的原子性和隔离性(原子性通过同步写日志实现崩溃恢复;隔离性通过每个对象上锁实现单线程访问),以及更复杂的原子操作,如自增 和 CAS。所以要注意这一点,看是否满足自己的应用场景。

多对象事务,除了要处理复杂原子性和隔离性,分布式场景下,还会涉及到跨分区(不能分区可能在不同的机器上),即分布式事务。

隔离级别

如果两个事务不触及相同的数据,它们可以安全地并行执行,因为两者都不依赖对方。当一个事务读取另一个事务同时修改的数据,或者两个事务试图同时修改相同的数据,并发问题才会出现。

并发bug很难通过测试找到,因为这样的错误只有在特殊时机下才会触发,很难重现。出于这个原因,数据库一直试图通过提供事务隔离来隐藏应用开发者的并发问题。事务隔离级别越强越能够避免发生的并发问题,比如可序列化保证事务的效果与串行执行是一样的,但这意味着并发性能的牺牲。所以数据库系统通常使用较弱的隔离级别,来防止一部分并发问题,而不是全部,所以了解这些对于开发出正确的应用非常重要。

当数据库遇到分布式,你会怎么做?

当数据库遇到分布式,你会怎么做?

脏写

脏写是指一个事务覆盖另一个事务未提交的数据,现有的隔离级别都会保证没有脏写。数据库通常使用行锁来防止脏写。

脏读

脏读是指一个事务写了部分数据,未提交,这是另一个事务读取到了这部分未提交的数据。

不可重复读

同一个事务两次读取的数据(读偏差) 或者 读取的记录数(幻读)不一致

丢失更新

两个事务同时读取数据,并进行更新,两个事务都更新成功,更新逻辑都是基于原先读取的值,但是事务提交会改变先前读取的值,导致丢失更新。典型的场景就是 读 -> 改 -> 写。

写偏差

可以将写入偏差视为丢失更新问题的一般化。如果两个事务读取相同的对象,然后更新其中的一些对象(不同的事务可能更新不同的对象),则可能发生写入偏差。

读已提交

读已提交提供两种保证

从数据库读时,只能看到已经提交的数据(没有脏读)

写入数据库时,只能覆盖已经写入的数据(没有脏写)

可重复读/快照隔离

支持快照隔离的数据库保留了一个对象的不同的提交版本,因为各种正在进行的事务可能需要看到数据库在不同时间点的状态。这种技术被称为多版本并发控制(MVCC,multi-version concurrency control)。

当一个事务开始,它被赋予一个唯一个的,永远增长的事务ID(txid)。每当事务向数据库写入任何内容时,它所写入的数据都会被标记上写入者的事务ID。

一个事务能查到一个对象,满足以下两个条件:

读事务开始时,创建该对象的事务已经提交

对象未被标记为删除,或如果被标记为删除,请求删除的事务在读事务开始时尚未提交

对于丢失更新和有数据交叉的写偏差,数据库可以结合快照隔,可以自动检测到丢失更新,中止相应的事务。但是MySQL/InnoDB的可重复读并不会检测丢失更新。有些作者认为,数据能防止丢失更新才能称得上快照隔离,所以这种定义下,MySQL并不提供快照隔离。

MySQL/InnoDB可重复读隔离级别下,可以使用 锁定读 (select for update)或者 比较并设置CAS 来避免丢失更新。

需要注意的是,如果数据库允许where字句从旧快照中读取,则此语句可能无法防止丢失更新,因为即使发生了另一个并发写入,where条件也可能是真的。

序列化

但对于写入数据无交叉的写偏差,只能通过序列化的隔离级别来避免,但是可以在应用层面通过 物化冲突的方式,人为的在数据库中引入一个锁对象。

序列化隔离级别有三种实现方式:

字面意义的串行顺序执行事务

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读