ACID
xuexs edited this page Apr 28, 2015
·
1 revision
事务一般应用在对数据准确性要求比较敏感的场合,所以在业务数据上,未必所有数据库的操作都需要使用到此“模拟事务”。
对可能需要用到事务的表,要求有如下几个公共的字段:
序号 | 字段 | 说明 |
---|---|---|
1 | _id | 标识列,即使不同的表,此id也不应该具有相同的值 |
2 | _dataLock | 锁标记 |
3 | _dataLockTime | 上锁时间,超过1分钟后自动解锁,依据是数据库操作超时达1分钟,基本是有问题 |
4 | _dataVersion | 数据版本号 |
5 | _transactionId | 事务id |
6 | _isDelete | 是否已经删除 |
对可能需要用到事务的表,要求有结构几乎一样的备份表,此备份表的作用不单止可以用于模拟事务,结合事务表,还能用于数据的回滚。
而对于备份表来讲,不管添加、修改还是删除数据,实际上的操作都为“添加”操作。
备份表之所以说是几乎一样,是因为记录原是表的id列名字变为“__id(左边双下划线)”,而备份表的“_id”作为备份表的标识列。
对可能需要用到事务的表,要对select操作增加一些复杂程度,但复杂性可以进行一致性的封装,实际对查询的时间影响其实很小。
事务与步骤表Transation
字段 | 说明 |
---|---|
_id | 标识列 |
transactionId | 事务编号 |
tableName | 关联表 |
dataId | 关联表某条数据的id |
fullKey | transactionId+’_’+ dataId(用于索引数据) |
operationType | 操作类型 |
creatTime | 添加时间 |
creatUserId | 添加用户,可以为null |
status | 事务状态 |
###实现流程
**事务的要求:**假设在任何环节出现问题,即使服务器突然断电还没把事务执行完毕,对用户来说,数据也能恢复到上一次准确的数据。
步骤 | 说明 |
---|---|
1 | 统计要对多少行数据进行操作(transationStepCount),生成事务id(与_id的生成规则一样即可) |
2 | 把相关数据存放到Base. Transation |
成功-go on ;失败-提示用户 | |
3 | 开始操作第1条数据 |
判断是否被锁定,而且锁定时间未过(如果是insert操作,则跳过此步) | |
否-go on;是-提示用户暂时不能修改此数据 | |
锁定当前数据(如果是insert操作,则跳过此步) | |
操作数据,其他自动状态: | |
{ | |
_dataLock:true | |
_dataLockTime: Transation. creatTime | |
_dataVersion: Transation. _id | |
} | |
成功-操作下一条数据;失败-中断事务,尝试恢复数据,提醒用户 | |
…… | |
4 | 全部成功 |
5 | 对每一条事务数据,在备份表增加一条备份数据 |
6 | 最后更新Transation的status为true |
成功-提示成功;失败-提醒用户,并尝试恢复数据 |
如上面的过程,操作失败在任何环节都可能发生。那在最极端的情况下,如何数据回滚,下面过程是数据恢复的核心,这个理解后,其他情况就简单了:
步骤 | 说明 |
---|---|
1 | 查询数据 |
2 | 根据当前数据的_transactionId到Transation查询最近的一次事务情况,检查事务的status是否为true |
3 | 当为false的时候 |
4 | 根据事务的关联性,尝试恢复数据 |
5 | 即使本条数据恢复失败,也从备份表把上一次正常的数据作为查询结果返回给用户 |
###总结
以上内容初看是复杂,逻辑上走得通,但要求编写数据库核心操作部分需要很高的严谨性,此操作方法写得好,对于上层的使用,还是传统的,调用insert、update和delete的操作。
by shiqiren 未经作者允许,不得转载 Email:shiqirenworld@qq.com