事务块是否会导致数据库或应用程序崩溃的 postgresql 中的错误提交?
Can a transactional block lead to erroneous commit in postgresql on db or app crash?
我正在编写一个新模块,在其中我全天每分钟从 kafka 轮询几千条记录,然后将它们分成两个 tables,然后提交给 kafka 代理。我打算 运行 对前一天收集的几百万条记录进行一些汇总查询
我将记录分成两个 table,因为负载本质上是动态的,我只对 json 负载中的几个字段感兴趣。我的假设是,即使聚合必须 运行 仅在两列上,即使在 运行 查询时,整个行也会加载到数据库的内存中。因此,只需从一开始就将负责计数的列提取到单独的 table 中。
Customer_Count 其中我 运行 聚合查询每个客户类型每个购买类型的计数。
Customer_Payload 其中我打算稍后将完整的有效负载归档到对象存储。
我计划在一个事务块中进行批量插入,首先插入有效负载 table,然后插入计数 table,假设在 tables 因为异常,应用程序或数据库崩溃导致对它们的批量插入回滚。
由于我将每个事务的几千条记录写入两个 tables,是否有可能在提交进行时数据库崩溃或应用程序崩溃导致部分写入 tables?
之一
我的假设是,由于这是同步事务,因此在数据库级别通过时提交之前的任何数据库崩溃都将被回滚。
对于 spring 引导应用程序中的任何崩溃都不会提交事务。
我格外谨慎,因为这些指标会导致下游的一些收入操作,因此存在关于部分提交可能性的问题。
table看起来有点像这样
计数 Table
create table customer_counts
(
id bigserial PK,
customer_id string Not Null,
count int,
purchase_type String,
process_dt date
)
create index metric_counts_idx on (customer_id, purchase_type, process_dt)
有效载荷table
create table customer_payload
(
id bigserial PK,
customer_id string Not Null,
payload text,
process_dt date
)
create index metric_payload_idx on (customer_id, process_dt)
那我运行一个
select sum(count), customer_id, purchase_type
from customer_counts
group by customer_id, purchase_type
一天结束时 table 有几百万条记录。
我只是使用负载 table 到 select 并推送到对象存储。
PS:我还想知道在 customer_id、purchase_type 上创建索引是否可以让我免于创建额外的 table 的麻烦计数,但根据我的阅读,索引仅用于查找,并且在加载整行后聚合将 运行 。您不能保证查询规划器是否每次都考虑索引。关于这种方法的任何建议也将有助于将我的设计从两个 table 简化为一个 table 将部分提交的问题限制为一个 table.
我计划使用 postgresql 中的默认设置进行事务和提交。我们使用 Spring Boot JdbcTemplate 进行数据库访问,并在 java 应用级别使用 @Transactional
块。有效载荷的大小在 0.5 KB 到 10 KB 之间变化。我还索引了客户 ID、purchase_type 和日期。 postgres 版本是 9.6.
您将看不到 partially-committed 笔交易。您的设置似乎没有什么值得担心的。
“整行”的说法不太对。 PG 实际上加载东西 page at a time, which usually means >1 row - but a page will only contain fairly compact row data, large values get compressed and stored out-of-band (aka TOAST)。如果您既不 select 也不过滤负载,您不应该最终读取其大部分字段数据。
至于你的 PS,我认为这实际上应该适合 index-only scan。 AIUI,你只会插入而不是 UPDATE/DELETEing,这应该意味着绝大多数 table 对所有事务都是可见的,这是使 index-only 扫描值得的重要因素。您可能希望在 customer_id、purchase_type 和计数上使用单个索引,这可用于满足您的最终查询。
我正在编写一个新模块,在其中我全天每分钟从 kafka 轮询几千条记录,然后将它们分成两个 tables,然后提交给 kafka 代理。我打算 运行 对前一天收集的几百万条记录进行一些汇总查询
我将记录分成两个 table,因为负载本质上是动态的,我只对 json 负载中的几个字段感兴趣。我的假设是,即使聚合必须 运行 仅在两列上,即使在 运行 查询时,整个行也会加载到数据库的内存中。因此,只需从一开始就将负责计数的列提取到单独的 table 中。
Customer_Count 其中我 运行 聚合查询每个客户类型每个购买类型的计数。
Customer_Payload 其中我打算稍后将完整的有效负载归档到对象存储。
我计划在一个事务块中进行批量插入,首先插入有效负载 table,然后插入计数 table,假设在 tables 因为异常,应用程序或数据库崩溃导致对它们的批量插入回滚。
由于我将每个事务的几千条记录写入两个 tables,是否有可能在提交进行时数据库崩溃或应用程序崩溃导致部分写入 tables?
之一我的假设是,由于这是同步事务,因此在数据库级别通过时提交之前的任何数据库崩溃都将被回滚。
对于 spring 引导应用程序中的任何崩溃都不会提交事务。
我格外谨慎,因为这些指标会导致下游的一些收入操作,因此存在关于部分提交可能性的问题。
table看起来有点像这样
计数 Table
create table customer_counts
(
id bigserial PK,
customer_id string Not Null,
count int,
purchase_type String,
process_dt date
)
create index metric_counts_idx on (customer_id, purchase_type, process_dt)
有效载荷table
create table customer_payload
(
id bigserial PK,
customer_id string Not Null,
payload text,
process_dt date
)
create index metric_payload_idx on (customer_id, process_dt)
那我运行一个
select sum(count), customer_id, purchase_type
from customer_counts
group by customer_id, purchase_type
一天结束时 table 有几百万条记录。
我只是使用负载 table 到 select 并推送到对象存储。
PS:我还想知道在 customer_id、purchase_type 上创建索引是否可以让我免于创建额外的 table 的麻烦计数,但根据我的阅读,索引仅用于查找,并且在加载整行后聚合将 运行 。您不能保证查询规划器是否每次都考虑索引。关于这种方法的任何建议也将有助于将我的设计从两个 table 简化为一个 table 将部分提交的问题限制为一个 table.
我计划使用 postgresql 中的默认设置进行事务和提交。我们使用 Spring Boot JdbcTemplate 进行数据库访问,并在 java 应用级别使用 @Transactional
块。有效载荷的大小在 0.5 KB 到 10 KB 之间变化。我还索引了客户 ID、purchase_type 和日期。 postgres 版本是 9.6.
您将看不到 partially-committed 笔交易。您的设置似乎没有什么值得担心的。
“整行”的说法不太对。 PG 实际上加载东西 page at a time, which usually means >1 row - but a page will only contain fairly compact row data, large values get compressed and stored out-of-band (aka TOAST)。如果您既不 select 也不过滤负载,您不应该最终读取其大部分字段数据。
至于你的 PS,我认为这实际上应该适合 index-only scan。 AIUI,你只会插入而不是 UPDATE/DELETEing,这应该意味着绝大多数 table 对所有事务都是可见的,这是使 index-only 扫描值得的重要因素。您可能希望在 customer_id、purchase_type 和计数上使用单个索引,这可用于满足您的最终查询。