我正试图通过每天的ETL Spark作业将S3上的Spark数据库与旧的Oracle数据库同步。我试图理解Spark在连接到像Oracle这样的RDS获取数据时会做什么。
它是否只抓取Spark向数据库请求时的数据(即,如果它在2/2 17:00:00从Oracle数据库中获取数据,它将只抓取到该时间点的数据)?本质上说,2/2 17:00:01的任何新数据或更新都不会从数据提取中获得?
这取决于情况。通常,您必须假设这种行为是不确定的,除非您的应用程序和数据库设计明确地确保了这一点。
默认情况下,每次对相应的Spark数据集执行操作时,Spark都会获取数据。这意味着每次执行都可能看到数据库的不同状态。
这种行为可能受到多种因素的影响:
- 显式缓存和可能的缓存驱逐
- 带有shuffle文件的隐式缓存
- 您在JDBC数据源中使用的一组经过检查的参数
在前两种情况下,Spark可以重用已经提取的数据,而无需返回到原始数据源。第三个更有趣。默认情况下,Spark使用单个事务获取数据,但也有一些方法可以基于列范围或谓词进行并行读取。如果使用其中一个,Spark将使用多个事务获取数据,每个事务都可以观察到数据库的不同状态。
如果需要一致的时间点语义,基本上有两个选项:
- 在数据库中使用不可变、仅追加和带时间戳的记录,并从Spark发出依赖于时间戳的查询
- 执行一致的数据库转储,并将其用作Spark作业的直接输入
虽然第一种方法的功能要强大得多,但如果您使用的是每种现有架构,那么实现起来就困难得多。