第一周作业-职业规划

1.什么是MVCC?有什么作用?

多版本并发控制,在理解MVCC前,先了解一下锁的概念,当有两个或多个用户读写数据库时,为了保证数据的一致性,要给数据库上锁,锁分两种,读锁和写锁。

读锁也叫共享锁,当一个用户在读数据时,给数据加上读锁,此时其它用户还可以共享读这部分数据,但是不能更新数据,必须要等到前一用户读锁释放,然后给数据加上写锁,才能更新数据。
写锁也叫排它锁,顾名思义,数据加上写锁以后,其它用户不能读也不能写。

加锁保证了数据的一致性,但是数据在同一时间只能串行访问,特别是写锁时,为了让更多用户或连接同时访问数据,锁的粒度细分可以增加并发,锁的粒度分为表锁,行锁。比如一个用户在更新A表,另一个可以访问B表,相互不受影响,这是表锁,还有行锁,一个用户在更新A表的a行,另一个用户可以访问A表的b行,也互不影响。所以粒度越细,并发越高,但是开销也越大。

理解了锁和锁的粒度以后,再来看MVCC,为了更进一步提高并发,特别是一些读多写少的应用系统,MVCC对数据行提供多个版本的数据快照功能,使同一数据读写操作可以并发进行。但也会引出不可重复读,幻读问题。

Innodb中的MVCC实现的方法是给每行数据添加两个隐式字段,创建时间和删除时间,这里的时间不是真的时间,应称为系统版本号,系统每开始一个事务,系统版本号递增,新开始的事务将系统版本号作为事务的版本号,当一个用户在读某行数据时,只会读到创建时间小于等于自己版本号(假定版本号为1),删除时间大于自己的版本号或者为空的数据,另一事务(版本号为2)此时对数据a进行更新操作,会先将自己的版本号2写入a的删除时间字段,然后新增一条更新过的数据c,将版本号2写入c的创建时间字段,如果事务2要删除某行b,只需将自己的版本号2写入数据b的删除时间字段内。此时前一个事务1还是可以读到数据a和c,因为a,c数据的删除时间大于事务1的版本号。却读不到数据b,因为数据b创建时间大于事务1。当然这只是简化的理解,实际运行要复杂得多。

所以MVCC的作用主要为了保证数据的一致性同时,提供高并发能力。下面的隔离级别会详细描述。

2.ACID中的I是怎么实现的?

ACID是支持事务数据库的必备特性,分别是原子性,一致性,隔离性,持久性。
其中隔离性是指一个事务开始后但还未提交,其它事务是看不到这个事务更新的结果的。
隔离性有四个级别,分别是read uncommitted未提交读,read committed提交读,repeatable read可重复读,serializable可串行化。
其中read uncommitted 级别,举例如事务1按执行顺序对要操作的数据a加锁,操作数据a,释放a锁 ... 获得数据b锁,操作数据b,释放b锁。在未提交前,事务2可以读到已经更新过的数据,如果此时事务1执行回滚,那么事务2读到的数据就是脏数据,也叫脏读。

为了解决脏读,引入第二个隔离级别read committed ,当事务1要操作一组数据时,会先获得数据的读锁或写锁,但是用完以后不会马上释放,而是等到事务提交或回滚时一起释放。这种办法就叫2PL(两阶段锁协议),这样就解决了脏读,如果事务2想要读事务1已经更新但未提交的数据,需获得数据的读锁,而事务1在未提交前是不会释放写锁的,所以事务2只能等待事务1释放锁。虽然解决了脏读,但是会引起新的问题死锁,当两个事务都在等待对方已经持有的锁时,就会发生死锁,所以必须设计检测死锁机制。
另外还有一个问题叫不可重复读,有的应用系统希望事务内读取的数据始终一致,即事务1开始后查询了一组数据a,同时事务2更新了数据据a并提交了,此时事务1再次查询数据a,发现跟第一次查询时不一致了。如果单单使用2pl协议是不会产生不可重复读问题的,为什么?因为事务1开始查询数据a时,事务2不可能获得数据a的写锁来更新数据。可是为什么还是会有这个问题,这是因为使用两阶段锁协议后,数据的吞吐量降低了,相当于串行化了事务。所以mysql引入MVCC来提高性能,并发读写时,相互不阻塞,而利用精巧的版本控制功能解决脏读,不可重读问题。但是写写仍然要使用锁机制。
第三个级别是repeatable read可重复读 ,如上所述利用MVCC可以解决不可重读的问题。但还是有一个幻读问题,即事务1开始后读取数据集a是n条,此时事务2在表中新增一条记录并提交,事务1再次读取数据集a是n+1条。称为幻读。mysql用next-key lock来解决,简单理解即事务1在第一次读(当前读)数据时,给符合条件的数据行及涉及到的范围加锁(record lock+Gap lock),这样其它事务就不能新增数据了。从而解决幻读问题。
至于第四个级别serializable,强制将所有事务串行化,大大降低并发。
本节参考http://hedengcheng.com/?p=771
本节参考https://www.zhihu.com/question/30272728/answer/132403859

3.2PC在数据库中是怎么来实现的?

两阶段提交协议(Two-phase Commit,2PC)经常被用来实现分布式事务。在分布式事务数据库中,每个节点(参与者)并不知道其它节点事务的执行情况,这里需要一个总协调角色参与统一管理。
第一阶段:协调者询问参与者能否可以提交事务。如果参与者事务操作执行成功则回复yes,反之no
第二阶段:参与者全部回复yes,协调者发出提交事务命令,参与者提交后回复完成给协调者。如果有一个参与者回复no,那么协调者发出中止命令,所有参与者回滚事务,回滚完成回复完成给协调者。
2PC协议因为网络延迟,协调者宕机等原因存在单点故障,网络阻塞的问题。

4.简单讲讲CAP/base/paxos算法。

CAP理论认为Consistency (数据一致性),Availability (可用性,正常响应),Partition Tolerance (分区容错性,节点宕机或网络故障仍保证一致性和可用性)这三种特性不能同时满足,只能满足其二。
简单的理解CAP理论,假如有两台服务器A和B,运行着相同的数据库DB0,在正常的情况下,用户更新了A上的DB0,变成DB1,A与B通信进行同步,这时另一用户访问B上的DB,查看到的也是最新的DB1,这样保证了一致证,和可用性,但是当A与B之间的通信断开时,用户更新了A上到DB2,B上还是DB1,这时另一用户再访问B时,要么牺牲一致性,返回DB1给用户,要么让用户等待通信恢复,也是就牺牲可用性。
那么通信在断开形成网络孤岛时,如何在可用性与一致性做出平衡呢,ACID理论要求保持强一致性,宁愿暂停服务;BASE则想保持高可用,容许数据暂时不一致。这是两种不同的设计理念。
BASE的意思是指:
基本可用(Basically Available)允许部份功能不可用,核心功能可用就行。
软状态( Soft State) 允许系统存在一种中间状态,
最终一致性( Eventual Consistency)数据可以因网络延迟或宕机有不一致的情况,但是经过一段时间最终可以达到一致。
paxos
Paxos是一种能够基于多节点在不可靠的网络条件下却能可靠地实现共识的一致性的算法。
简单描述如下,pasos系统内有二种角色,一叫决策者,一叫提议者。
系统达成一项一致决定的过程分两个阶段:
首先是预决策阶段,此时任意提议者都可以向决策者发送包含编号的预提议申请,决策者根据提议者编号的新旧程度进行回复,如果提议者发送的编号是最新的,回复yes,并将编号存储起来,如果提议者的编号小于决策者存储的编号,那么回复no和存储的编号。
第二阶段是决策阶段,提议者A收到了大多数决策者回复的ok,于是正式向决策者发送提议信息a以及A的编号,决策者收到后,有两种情况:
1、如果在回复提议者A的ok信息之后一直到A再次发送正式提议信息a之间,都没有再收到其它大于提议者A编号的预提议信息。也就是说存储的编号仍然是提议者A申请的编号,那么决策者确定信息a为正式信息。将A的编号和提议信息都存起来。回复提议者A正式决定信息。提议者A统计回复的信息,如果占决策者的多数,则决议成功,向其它学习者广播。如果之后有其它提议者发送预提议申请,已经决定了的决策者会拒绝并回复提议内容a。
2、如果在回复提议者A的ok信息之后一直到A再次发送正式提议信息a之间,有其它提议者如B也发送了预提议申请信息,并且编号比A大,一部分决策者将B的编号存起来,并回复B准备好了OK信息。决策者是喜新厌旧的。所以这一部分决策者再次收到A的信息后,拒绝了A并回复了B的编号。A统计了一下决策者已经决策成功的总数量没有超过半数,很不甘心,于是将自己的编号在B的基础上加1后,再次向其它决策者发送预提议申请,回到第一阶段。
经过了这两个阶段后,每个提议者都可能获得了一些决策者的支持,每个提议者会根据回复的提议信息进行统计,将自己的提议改成支持最多的提议,直到形成半数以上决策者都同意了某个提议。决策结束。

你可能感兴趣的:(第一周作业-职业规划)