❶ 深入解析Oracle数据库安全策略
Oracle是关系型数据库管理系统,它功能强大、性能卓越,在当今大型数据库管理系统中占有重要地位。在正常情况下,Oracle数据库会保证数据的安全、稳定,为用户提供正确的数据,但由于计算机系统的故障(硬件故障、软件故障、网络故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使数据库中全部或部分数据丢失,整个系统都将处于瘫痪状态。因此,如何保证Oracle数据库的安全就陵慧掘成为整个系统安全的重要组成部分。
Oracle数据库的安全策略包括数据库的备份和恢复、用户角色管理。
一、数据库备份所使用的结构
Oracle数据库使用几种结构来保护数据:数据库后备、日志、回滚段和控制文件。
1.数据库后备是由构成Oracle数据库的物理文件的操作系统后备所组成。当介质故障时进行数据库恢复,利用后备文件恢复毁坏的数据文件或控制文件。
2.每一个Oracle数据库实例都提供日志,记录数据库中所作的全部修改。每一个运行的Oracle数据库实例相应地有一个在线日志,它与Oracle后台进程LGWR一起工作,立即记录该实例所作的全部修改。归档(离线)日志是可选择的,一个Oracle数据库实例一旦在线日志填满后,可形成在线日志归档文件。归档的在线日志文件被唯一标识并合并成归档日志。
3.回滚段用于存储正在进行的事务(为未提交的事务)所修改值的老值,该信息在数据库恢复过程中用于撤消任何非提交的修改。
4.控制文件,一般用于存储数据库的物理结构的状态。控制文件中某些状态信息在实例恢复和介质恢复期间用于引导Oracle。
二、在线日志
一个Oracle数据库的每一实例有一个相关联的在线日志。一个在线日志由多个在线日志文件组成。在线日志文件(online redo log file)填入日志项(redo entry),日志项记录的数据用于重构对数据库所作的全部修改。
三、归档日志
Oracle要将填满的在线日志文件组归档时,则要建立归档日志(archived redo log)。其对数据库备份和恢复有下列用处:
1.数据库后备以及在线和归档日志文件,在操作系统和磁盘故障中可保证全部提交的事物可被恢复。
2.在数据库打开和正常系统使用下,如果归档日志是永久保存,在线后备可以进行和使用。
数据库可运行在两种不同方式下:NOARCHIVELOG方式或ARCHIVELOG方式。数据库在NOARCHIVELOG方式下使用时,不能进行在线日志的归档。如果数据库在ARCHIVELOG方式下运行,可实施在线日志的归档。
四、Oracle的备份特性
Oracle备份包括逻辑备份和物理备份。
1.逻辑备份
数据库的逻辑备份包含读一个数据库记录集和将记录集写入文件。
(1)输出(Export)输出可以是整个数据库、指定用户或指定表。
(2)输入(Import)输入将输出建立的二进制转储文件读入并执行其命令。
2.物理备份
物理备份包含拷贝构成数据库的文件而不管其逻辑内容。
Oracle支持两种不同类型的物理文件备份:脱机备份(offline backup)和联机备份(online backup)。
(1) 脱机备份
脱机备份用在当数据库已正常关闭,数据库处于"offline"时,要备份下列文件:
所有数据文件
所有控制文件
所有联机日志
init.ora(可选的)
(2) 联机备份
联机备份可用来备份任何运作在ARCHIVELOG方式下的数据库。在这种方式下,联机日志被归档,在数据库内部建立一个所有作业的完整记录。
联机备份过程具备强有力的功能。第一,提供了完全的时间点尺核(point-in-time)恢复。第二,在文件系统备份时允许数据库保持打开状态。
备份方式特性比较
五、Oracle数据库的角色管理
Oracle数据库系统在利用角色管理数据库安全性方面采取的基本措施有:
通过验证用户名称和口令,防止非Oracle用户注册到Oracle数据库,对数据库进行非法存取操作。
授予用户一定的权限,限制用户操纵数据库的权力。
授予用户对数据库实体的存取执行权限,阻止用户访问非授权数据。
提供碧孙数据库实体存取审计机制,使数据库管理员可以监视数据库中数据的存取情况和系统资源的使用情况。
采用视图机制,限制存取基表的行和列集合。
六、Oracle数据库的安全策略
由于Oracle数据库备份有三种方式,每种方式具有不同的恢复特性,因此应集成数据库与文件系统备份,集成逻辑备份和物理备份。
(一)、备份策略
在操作系统级别,使用大容量磁盘阵列,通过磁盘映像技术使每一个数据库文件自动分布于每个物理磁盘。这样,当某个磁盘出现物理损坏时,操作系统会自动引发映像磁盘来取代失效的磁盘,保证数据库的正常运行。
在多个不同的物理磁盘上保持多个控制文件的备份。控制文件在数据库恢复期间用于引导Oracle,因此保持多个控制文件的备份,可以确保在出现磁盘故障后,能有可用的控制文件用于数据库恢复。
使数据库运行在ARCHIVELOG(归档)方式下,归档日志存放于另一映像的逻辑磁盘上。每晚进行一次联机备份操作,备份所有数据文件、所有归档日志文件、一个控制文件。每周进行一次输出(Export)操作。
(二)、恢复策略
1.实例失败
从实例失败中恢复是自动进行的。实例失败一般是由服务器失败引起的,当数据库实例失败后,重新启动服务器,启动数据库,Oracle检查数据文件和联机日志文件,并把所有文件同步到同一个时间点上。
2.磁盘失败
如果丢失的是控制文件,只要关闭数据库,从保留有控制文件的地方拷贝一份即可。
如果丢失的是数据文件,可用前一天晚上的联机备份进行恢复,步骤如下:
1)从备份中把丢失的文件存在原来位置。
2)加载数据库
3)恢复数据库
4)打开数据库
3.错误删除或修改对象
在这种情况下,一般希望能追溯返回到错误发生前的那个时间点上。这叫做时间点恢复。完成恢复的步骤如下:
1)从当前数据库输出(Export),输入(Import)到备用数据库,使备用数据库与当前数据库保持一致。
2)向前滚动备用数据库到错误发生前的那个时间点。
3)从备用数据库输出受错误影响的逻辑对象。
4)使用上一步产生的输出文件输入那些受影响的对象到当前数据库。
(三)、用户角色管理
1.对所有客户端按工作性质分类,分别授予不同的用户角色。
2.对不同的用户角色,根据其使用的数据源,分别授予不同的数据库对象存取权限。
基于以上的安全策略,可以防止非法用户访问数据库,限制合法用户操纵数据库的权限;可以使数据库在故障发生后,不会丢失任何数据,并能使数据库迅速恢复到故障发生前的那一时间点上,最大限度的保证数据的安全和整个系统的连续运行。
❷ Flink sql 知其所以然(五)| 自定义 protobuf format
protobuf 作为目前各大公司中最广泛使用的高效的协议数据交换格式工具库,会大量作为流式数据传输的序列化方式,所以在 flink sql 中如果能实现 protobuf 的 format 会非常有用( 目前社区已经有对应的实现,不过目前还没有 merge,预计在 1.14 系列版本中能 release )。
issue 见: https://issues.apache.org/jira/browse/FLINK-18202?filter=-4&jql=project%20%3D%20FLINK%20AND%20issuetype%20%3D%20%22New%20Feature%22%20AND%20text%20~%20protobuf%20order%20by%20created%20DESC
pr 见: https://github.com/apache/flink/pull/14376
这一节主要介绍 flink sql 中怎么自定义实现 format ,其中以最常使用的 protobuf 作为案例来介绍。
如果想在本地直接测试下:
关于为什么选择 protobuf 可以看这篇文章,写的很详细:
http://hengyunabc.github.io/thinking-about-grpc-protobuf/?utm_source=tuicool&utm_medium=referral
在实时计算的领域中,为了可读性会选择 json ,为了效率以及一些已经依赖了 grpc 的公司会选择 protobuf 来做数据序列化,那么自然而然,日志的序列化方式也会选择 protobuf 。
而官方目前已经 release 的版本中是没有提供 flink sql api 的 protobuf format 的。如下图,基于 1.13 版本。
https://ci.apache.org/projects/flink/flink-docs-release-1.13/docs/connectors/table/overview/
因此本文在介绍怎样自定义一个 format 的同时,实现一个 protobuf format 来给大家使用。
预期效果是先实现几种最基本的数据类型,包括 protobuf 中的 message (自定义 model)、 map (映射)、 repeated (列表)、其他基本数据类型等,这些都是我们最常使用的类型。
预期 protobuf message 定义如下:
测试数据源数据如下,博主把 protobuf 的数据转换为 json,以方便展示,如下图:
预期 flink sql:
数据源表 DDL:
数据汇表 DDL:
Transform 执行逻辑:
下面是我在本地跑的结果:
可以看到打印的结果,数据是正确的被反序列化读入,并且最终输出到 console。
目前业界可以参考的实现如下: https://github.com/maosuhan/flink-pb , 也就是这位哥们负责目前 flink protobuf 的 format。
这种实现的具体使用方式如下:
其实现有几个特点:
[图片上传失败...(image-66c35b-1644940704671)]
其实上节已经详细描述了 flink sql 对于 sourcesinkformat 的加载机制。
如图 serde format 是通过 TableFactoryHelper.discoverDecodingFormat 和 TableFactoryHelper.discoverEncodingFormat 创建的
所有通过 SPI 的 sourcesinkformt 插件都继承自 Factory 。
整体创建 format 方法的调用链如下图。
最终实现如下,涉及到了几个实现类:
具体流程:
上述实现类的具体关系如下:
介绍完流程,进入具体实现方案细节:
ProtobufFormatFactory 主要创建 format 的逻辑:
resourcesMETA-INF 文件:
主要实现反序列化的逻辑:
可以注意到上述反序列化的主要逻辑就集中在 runtimeConverter 上,即 ProtobufToRowDataConverters.ProtobufToRowDataConverter 。
ProtobufToRowDataConverters.ProtobufToRowDataConverter 就是在 ProtobufToRowDataConverters 中定义的。
ProtobufToRowDataConverters.ProtobufToRowDataConverter 其实就是一个 convertor 接口:
其作用就是将 protobuf message 中的每一个字段转换成为 RowData 中的每一个字段。
ProtobufToRowDataConverters 中就定义了具体转换逻辑,如截图所示,每一个 LogicalType 都定义了 protobuf message 字段转换为 flink 数据类型的逻辑:
源码后台回复 flink sql 知其所以然(五)| 自定义 protobuf format 获取。
本文主要是针对 flink sql protobuf format 进行了原理解释以及对应的实现。
如果你正好需要这么一个 format,直接后台回复 flink sql 知其所以然(五)| 自定义 protobuf format 获取源码吧。
当然上述只是 protobuf format 一个基础的实现,用于生产环境还有很多方面可以去扩展的。
❸ 彻底搞懂JDBC的运行过程
前几天笔者发布了博客,手写mybatis彻底搞懂框架原理。为了帮助初学者更好理解mybatis框架,这次讲解一下Java的JDBC的运行过程。
JDBC的作用
JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库。JDBC接口及相关类在java.sql包和javax.sql包里。我们可以用它来连接数据库,执行SQL查询,存储过程,并处理返回的结果。
JDBC接口让Java程序和JDBC驱动实现了松耦合,使得切换不同的数据库变得更加简单。
JDBC的连接步骤
执行一次JDBC连接,分六个步骤进行:
1. 导入包
在程序中包含数据库编程所需的JDBC类。大多数情况下,使用 import java.sql.* 就足够了
2. 注册JDBC驱动程序
需要初始化驱动程序,这样就可以打开与数据库的通信。
3. 打开一个连接
使用DriverManager.getConnection()方法来创建一个Connection对象,它代表一个数据库的物理连接。
4. 执行一个查询
需要使用一个类型为Statement或PreparedStatement的对象(两者区别看后文),并提交一个SQL语句到数据库执行查询。
5. 从结果集中提取数据
这一步中演示如何从数据库中获取查询结果的数据。使用ResultSet.getXXX()方法来检索的数据结果
6. 清理环境资源
在使用JDBC与数据交互操作数据库中的数据后,应该明确地关闭所有的数据库资源以减少资源的浪费。本文使用了try with resources方式关闭资源,这是JDK7的语法糖,读者可自行搜索。
完整代码如下。
JDBC的最佳实践
JDBC是如何实现Java程序和JDBC驱动的松耦合?
JDBC API使用Java的反射机制来实现Java程序和JDBC驱动的松耦合。看一下上文的JDBC示例,你会发现所有操作都是通过JDBC接口完成的,而驱动只有在通过Class.forName反射机制来加载的时候才会出现。
这是Java核心库里反射机制的最佳实践之一,它使得应用程序和驱动程序之间进行了隔离,让迁移数据库的工作变得更简单。
Statement和PreparedStatement区别
预编译
创建时的区别:
执行时的区别:
由上可以看出,PreparedStatement有预编译的过程,已经绑定sql,之后无论执行多少次,都不会再去进行编译,而Statement 不同,如果执行多次,则相应的就要编译多少次sql,所以从这点看,PreparedStatement的效率会比Statement要高一些。PreparedStatement是预编译的,所以可以有效的防止SQL注入等问题
占位符
PrepareStatement可以替换变量在SQL语句中可以包含?,可以用?替换成变量。
而Statement只能用字符串拼接。
JDBC的ResultSet
在查询数据库后会返回一个ResultSet,它就像是查询结果集的一张数据表。
ResultSet对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了ResultSet的next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回false。可以在for循环中用它来遍历数据集。
默认的ResultSet是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的ResultSet,像下面这样。
当生成ResultSet的Statement对象要关闭或者重新执行或是获取下一个ResultSet的时候,ResultSet对象也会自动关闭。
可以通过ResultSet的getter方法,传入列名或者从1开始的序号来获取列数据。
ResultSet的不同类型
根据创建Statement时输入参数的不同,会对应不同类型的ResultSet。如果你看下Connection的方法,你会发现createStatement和prepareStatement方法重载了,以支持不同的ResultSet和并发类型。
ResultSet对象有三种类型。
ResultSet有两种并发类型。