您的位置:首页 > 其它

分布式事务(ACID)

2021-03-01 23:33 441 查看
隔离级别

读未提交  (RU)  可以读取正在修改的数据

读已提交 (RC)  可以读取修改后的数据,不可读取正在修改的数据

可重复读 (RR)   多次读取 前后都一致,别的事务插入修改的数据不会读到

串化     (SR)

事务并发带来隔离问题

1 脏读:事务A读取事务B正在更新的数据,然后B回滚操作,那么事务A读取到的数据是脏的。

2 不可重复: 事务A多次读取同一批数据,事务B在事务A多次读取过程中,对数据做了更新提交操作。
导致事务A前后读取数据不一致。

3 幻读:事务A修改数据,事务B插入一条件数据,事务A再读的时候发现还有一笔数据没有修改。

隔离级别与并发问题

读未提交  (RU)  可脏读,可幻读,不可重复读

读已提交 (RC)  不可, 可幻读,不可重复读

可重复读 (RR)   不可 , 可幻读,   可重复读

串化     (SR)      不可     不可    可

单机数据库如何解决?

单机数据库为了解决ACID问题,各家数据库厂商基本使用事务+锁+MVCC 来保证。

原子性: 事务+锁 方式去实现

一致性: 也是事务去解决

隔离级别:ORACLE通过 UNDO+事务+锁 实现RC隔离级别,同时避免幻读,不可重复读

什么是事务,事务是个概念,是保证数据修改前后一致性,不能修改100行数据,其中50行修改成功,另外50行修改失败。

也不能在业务逻辑上造成前后数据不一致,比如A帐号扣了50成功,B帐号增加50失败。

因此从上面可以得知,事务有单语句和多语句组成。

默认下单条语句自动开启事务,而多语句需要手工开启

用下面命令 把多条语句打包在一起。

begin trasction

commit;

通过事务提示,数据库把语句所修改的行,要么一起修改OK,要么一起修改失败。

假如出现部分成功,部分失败 咋办?就把修改成功的进行回滚。

从而通过事务 完成了原子性要求。

分布式事务(ACID)

那么在分布式数据库下,我们的事务,或者修改语句都下发到下面4个或多个分片上。

每个分片独立的单机数据库。

假如下发一个分片,还不错,可以充分利用下面数据库固有的机制去实现原子性

假如下方多个分片的事务呢?

比如单条修改语句,下发到4个分片上,其实默认是把1个大事务,拆成4个子事务。

把4个子事务下发到下面数据库去执行。

那么同样如单机数据库部分行修改成功,部分修改不成功的情况。

比如2个分片修改成功,另外2个分片修改失败。

失败原因可能分片数据库挂了,遇到锁等待,遇到死锁本子事务被杀了

那么要在上层登记每个事务在不同分片的执行情况,执行成功标记OK,否则就FAILE

GTID,SQL_ID,SHADING01,SHARDING02,SHAGDING03,SHADING04

00X1 S02, OK , OK FAILE FAILE

对部分修改成功,OK的分片进行回滚,

另外要对下发的事务设置个TIEM_OUT,超时后认为执行失败,对成功的下发ROLLBACK命令。

多语句的事务,我们增加个SQL_ID,要求本事务所有SQL在所有分片节点上执行要OK,任何一个FAILE都要回滚。

一致性

在分布式应该不是问题,因为每个查询下发后面数据库,都是利用数据库的MVCC进行快照读,

遇到了事务锁定记录,也会去MVCC UNDO里面读旧数据。

也会遇到这样的问题,比如说T1时间读了2个分片,在T2时间读后面2个分片的数据,而这2个分片数据已被修改提交。

因为下发到后面2个分片的时间有差异,造成4个分片的数据前后不一致性。

中兴DB设计是上面搞个GTID,下面每个表有个隐藏列GTID,每个个查询也获得GTID,然后跟行的GTID对比

如果数据被更新了,则读取失败。没有利用MVCC机制,写居然阻塞了读。

这样就要修改MYSQL PG的源代码,向外提高接口,提高依据GTID值进行回滚查询,MVCC快照读。

同样 重复读和幻读 在分布式环境下 比较难做到,因为无法利用下面的数据库的MVCC机制(MYSQL,PG,ORACLE)

所以也要修改MYSQL内核,添加分布式MVCC接口,上面计算节点中间件,通过该接口下发事务或查询语句。

每个事务和查询语句携带GTID或者是SCN等时间措标志。下面数据库每行数据增加一列 存放GTID(SCN,TIMESTAMP)。

通过分布式接口的语句依据隐藏的GTID来判断是否要快照读。而非分布式接口就按原来的MYSQL的事务ID去,或者ORACLE的SCN。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: