oracle 体系结构
1.猜想
1.1 为什么需要数据库?
- 存储数据
- 查询数据
- 用户权限管理
- 分布式数据隔离管理
- 事务回滚
1.2 为什么需要学习数据库?
开发人员
- 合理设计数据模型
- 提升项目性能,实现单车变火箭的优化
- 编写更快更高效的sql
- 理解数据库底层原理,利于解决项目中的突发情况
...
1.3 如果你来设计一款数据库,你会怎么来设计?
1.首先,我们需要连接数据库,因此用户权限认证是必须的
2.其次,数据要通过磁盘进行存储,根据数据类型的不同来管理数据文件
3.再次,我们需要查询数据,由于磁盘IO 比较慢,添加数据缓存区是有必要的吧
4.那么问题来了,数据都存在磁盘,我们怎么让数据库提供服务呢?
Oracle
- 体系结构图
查询sql (select * from t where id =2) 在体系中如何流转?
PGA内存区中保存用户+权限信息->SQL 指令匹配成一条唯一的hash 值
-> 2区 SGA的共享池
-> 查询是否有这个sql指令的身份证
-> 开始进行解析
-> 3区database 数据区
第二次读和第一次读的物理读会少很多(以下截图来自《收获,不止oracle》)
根据查询流程可知,查询主要是涉及体系图的PGA、SGA、数据文件。
2. 那么其他process(DBWR、LGWR、CKPT、PMON、LCKn、RECO、SMON),又有什么用?现在我们来介绍Update **
2.1 update 的正常流程
2.2 update 如何实现数据的回滚?
2.3 update 一致读 Q. 查询结果是以查询时刻的数据返回,还是返回结果时刻的数据返回?
eg.1 应聘者查询面试结果 面试者小明 8点半开始查询面试结果,9点才返回数据,小明面试通过的结果在8点50录入,小明等待了半个小时。这个时候,是不是应该按照返回时刻的数据返回,要不然,9点返回没有面试结果,换做是我们,明明有结果,却告知没结果,那不是很难过?
eg.2 一个人多个账户信息,查询结果 我在某银行同时开了2个账户(A ¥2000,D ¥2000),8点我去银行柜台发起了一笔转账,使用A账户给D 账户转账500,又由于数据某些问题,耗时过长,8点半才转账完成。 回家的路上我有点不放心,8:29 去查询账户信息,由于操作没有提交, 数据库查询从A 账户 还没有发生扣减500, 所以账户还是2000。 查询D 账户的时候,操作commit,D 账户此时已经是 2500。 如果按照返回时刻决定,此时,我的账户总额为4500,凭空多了500 块,我是不是应该请大家吃饭呢?
Oracle 为了实现一致读,内部设计一个SCN 标志(全称System Change Number),这是一个只会增加不会减少的递增数字,存在于oracle 的最小单位块里,当某块改变时,SCN就会递增。
当我早上8点整开始查询数据库,首先会获取8点那个时刻的SCN号,并记录下来,比如是SCN8:00。 查询过程中,如果这些快的SCN其实都小于SCN,说明该块在这段时间内确实没有被更新过,我们放心读,总金额就是2000+2000 = 4000. 加入8点以后有更新,发生转账动作,又会发生什么呢? 8点30分,A 账户转500 到D 账户,A 账户变为1500,D 账户变为2500,此时A 账户所在的块1 和账户D 所在的块2 SCN 同时改变,变为SCN 8:30, 当数据库查询到块4时,发现块4 的头部的ITL槽中的SCN号SCN8:30,大于发出查询时间的SCN8:00,说明该数据在8点以后被更新了,于是根据ITL槽中记录了对应的undo块的地址找到undo 块,将undo块中的被修改前的数据(2000)取出。
这是oracle 实现一致读的方式,那么sql server 一致读的方式是边读边上锁,也能实现一致读效果,这样做有什么坏处呢?
☆ 评选劳模
PMON Processes Monitor 进程监视器,如果在执行某些更新语句,未提交时进程崩溃了,这时候PMON 会自动回滚该操作,无需人工去执行rollback命令。
SMON system monitor,可以理解为系统监视器,与PMON 不同的是,SMON 关注的是系统级的操作而非单个进程,工作重点在于实例恢复,除此之外还有清理临时表空间、清理回滚段表空间、合并空闲空间等。
DBWR oracle 最核心的进程之一,负责把数据缓存区写到磁盘里,该进程和CKPT相辅相成。如果LGWR出现故障,DBWR此时还是会不听CKPT的命令罢工的,直接将数据写入磁盘。 数据从数据缓存区刷出到database 中,是批量还是单次?批量的体量和oracle性能的关联关系? 批量的数据越大,恢复时间越长。
CKPT 控制数据缓存区中的数据写到磁盘的动作,触发DBWR
RECO 用于分布式数据库的恢复,适用于两阶段提交的应用场景。(比如面临多个数据库A,B,C,某个应用跨越三个数据库,在发起的过程中需要A、B、C都提交成功,事务才会成功),只要有一个失败,就必须全部回滚。
LCKn 仅用于RAC 数据库,最多可有10个进程(LCK0,LCK1,...LCK9),用于用例间的封锁。
LGWR:把日志缓存区中的数据从内存写到磁盘的REDO 文件中,完成创建数据库对象,更新数据等操作过程的记录。日志缓存区保存了数据库相关操作的日志,记录了这个动作,然后由LGWR 后台进程将其从日志缓存区写入磁盘的日志文件里。(如何恢复栗子) 1.A动作,建立一张表T 2.B动作,在T表中插入一条数据 3.C动作,用该数据更新某字段 a.如果T表记录被人误删,怎么办? b.如果整张表都被人删除了,怎么办?
ARCH进程在LGWR写日志写到需要被覆盖重写的时候,触发arch进程去转移日志文件,将日志文件复制出去形成归档日志文件,意面日志丢失。
经过上述查询和更新操作的介绍,关于谁是劳模这个问题,应该已经非常清晰了。让我们恭喜LGWR!
一、每隔三秒,LGWR运行一次。 二、任何COMMIT触发LGWR运行一次。 三、DBWR要把数据从数据缓存写到磁盘,触发LGWR运行一次。 四、日志缓存区满三分之一或记录满1MB,触发LGWR运行一次。 五、联机日志文件切换也将触发LGWR。
以上内容均参考自《收获,不知oracle》,这是今年我看过最好的技术书,这本书以趣味性驱动又结合底层体系原理的方式进行讲解。让我收获巨大,除了oracle 的知识,还有作者反复提及的“少做事” 原则和解决问题的思维方式,都让人耳目一新,印象深刻。