聊一聊数据库并发控制和恢复机制
Concurrency
简单的说并发就是允许多个客户端访问一个数据库,但是如何处理并发请求却有一些学问,我们开始吧。
动物可以分为人和其它动物。数据库也可以按照这个逻辑划分。数据库分为SQLite和其它数据库。SQLite就是一个简单的文件,本身不提供通过网络访问的功能。要对它实现并发,一般做法是将它放在一个文件服务器上, 比如drobox.但是一旦有客户端进行写操作,其他客户端就不能进行任何操作了。
其他数据库实现并发更加高效,就是在存放数据库文件的电脑上同样运行着一台数据库服务器。
- 客户端发送SQL
- 客户端通过查询返回给客户端结果。
在往下看之前,我们需要复习一下两个基本概念。
- Transaction(事务): a transaction is a sequence of statements.
- ACID
- Atomic. 一旦一个事务要不被全部执行,要不一个也没有执行。(这里涉及到回滚rollback)
- Consistent 执行事务后,数据库本身的约束不能变化
- Isolated 两个事务在人类看来是按顺序执行的,虽然本身他们可能是interleaved的
- Durable 提交后的事务应该被写入磁盘,永久存在。
简单的例子1
它违背了ACID的I.因为这两个的运行结果,在人类看来不可能是顺序执行的。
简单的例子2:serial execution
我们可以简单总结数据库操作时读,写和基本计算操作。如果T1和T2顺序执行,T2需要等待T1执行完毕,可明明T2更小,让T2等待这么长时间是不是不太合理?
不正确的并发
这个虽然实际上没有按顺序执行,但是和先执行T1,在执行T2结果是一样的。可是依旧有一个问题,如果T1在 Y:=Y+N
处执行失败了,怎么办?
- 回滚T1吗?那T2怎么办;
- 同时回滚T2吗?T2已经执行完毕了
这里就需要大家弄清这个概念: recoverable schedules
- 如果一个事务A要读一个数据,这个数据又被另一个B事物修改,就必须等待B事务提交。人类看来是这样的。
- 其实也有可能出现如上图的这种情况,这是实际执行顺序,人类认为是T2在T1后执行的。遇到这种情况,T2不能确认commit,必须等待T1commit.
Recovery
数据库恢复需要日志,日志简单分为
- undo log: a log that allows undoing changes
- Redo log: a log that allows redoing changes
- Undo/Redo log: Combination.
实际主流用到的是undo/redo log.
简单的undo log
在数据被写入磁盘之前,旧的数据会被写入日志,这样一旦事务失败,我们可以可以根据日志回滚。比如下图
但是这个不够高效,实际我们会使用缓存,减少写入磁盘的次数,同时查询也可以之前在内存中进行,一举两得,如下图
Redo Log
这个和undo log很像,不过它存储的是更改后的数据,这样就能保证,事务的失败的时候,可以从新来一遍,如下图
Undo/Redo Log
这种类型的日志就是前两者的结合体。
总结
日志是保证ACID的方法手段,使用日志肯定会降低性能,但是不能因为费时间就不吃饭了吧,哈哈。没有日志我觉得宇宙会随时爆炸,而且还不能重启。另外一个对并发很重要的概念就是锁。
我们下一篇再見,祝你愉快!
转载自:https://juejin.cn/post/7223357165682278459