6 个版本

0.2.1 2018年10月4日
0.2.0 2018年10月4日
0.1.3 2018年10月4日
0.1.2 2018年9月30日

1617数据库接口 中排名

Download history 85/week @ 2024-04-06 110/week @ 2024-04-13 61/week @ 2024-04-20 78/week @ 2024-04-27 78/week @ 2024-05-04 75/week @ 2024-05-11 178/week @ 2024-05-18 44/week @ 2024-05-25 51/week @ 2024-06-01 62/week @ 2024-06-08 131/week @ 2024-06-15 140/week @ 2024-06-22 195/week @ 2024-06-29 132/week @ 2024-07-06 132/week @ 2024-07-13 349/week @ 2024-07-20

每月831 次下载

MIT/Apache

22KB
298

用于识别和过期长时间运行的数据库活动的 Crate。该 Crate 提供的核心原语是 PleaseHandle。这些句柄表示长时间运行的操作,并可作为实现排他锁行为的依据,当锁可能被持有时间过长,以至于事务级锁定不可接受时。

文档


lib.rs:

Crate 用于识别和过期长时间运行的数据库活动。该 Crate 提供的核心原语是 PleaseHandle。这些句柄表示长时间运行的操作,并可作为实现排他锁行为的依据,当锁可能被持有时间过长,以至于事务级锁定不可接受时。

设置

此 Crate 需要某些表存在,因此它导出自己迁移。要管理第三方 Crate 的迁移,您可以安装 diesel-setup-deps 工具

cargo install diesel-setup-deps
diesel setup
diesel-setup-deps

必要的迁移将自动添加到您的 diesel 迁移目录中,这些迁移应与其他迁移一起提交到版本控制。

用法

首先,您通常有一个长时间运行的操作,您希望独占访问数据库的某些部分。

一个好的例子可能是生成报告:此操作将处理大量数据,然后将结果保存到我们的 output 字段中,在 reports 表中。我们希望操作具有对 output 字段的独占访问权,这样在操作运行时没有人会尝试生成报告,我们还想跟踪报告是否正在进行。

此操作可以作为一个单独的函数实现

fn generate_report(
    connection_pool: Arc<ConnectionPool>,
    report_id: i32
) -> PleaseResult<ConnectionPoolError> {

首先,我们获取一个句柄来表示我们的操作

    let mut handle = PleaseHandle::new_with_cleanup(
        connection_pool, "generating report"
    )?;

然后我们将句柄的 ID 存储在 reports 表中

    handle.transaction(|conn, handle_id| {
        diesel::update(
            reports::table
                .filter(reports::id.eq(report_id))
                .filter(reports::operation_id.is_null())
        )
        .set(reports::operation_id.eq(Some(handle_id)))
        .execute(conn)
    })?;

重要的是,如果操作 ID 已经设置,则失败。

现在,我们可以执行生成报告所需的任何工作。如果报告可能需要比操作超时更长的时间,那么您可以选择增加超时,或者每隔一段时间调用 handle.refresh() 来确保超时永远不会达到。

当我们得到结果时,我们只需将其保存并关闭句柄即可

    handle.transaction(|conn, handle_id| {
        diesel::update(
            reports::table
                .filter(reports::id.eq(report_id))
        )
        .set(reports::output.eq(Some(result)))
        .execute(conn)
    })?;

    handle.close()?;
    Ok(())
})

如果允许句柄超出作用域,则句柄将被自动关闭,但错误将被忽略。

数据库模式

在上面的示例中,预期 reports::operation_id 列是一个可空的整数列,并且是 please_ids 表的外键。

理想情况下,你应该设置级联规则,以便当从 please_ids 表中删除行时,相应的报告的 operation_id 列被设置为空。

操作超时

如果在 PleaseHandle 上没有活动超过 操作超时 的时间,则句柄可能会过期。这将在从另一个线程或另一个数据库客户端调用 perform_cleanupnew_with_cleanup 时自动发生。

调用 transactionrefresh 方法被认为是活动,并且可以防止句柄过期,前提是它尚未过期。如果操作已过期,这两种方法都会立即失败。在这种情况下,你应该取消任何作为操作一部分进行的操作。

操作超时由数据库函数控制:please_timeout()。要更改超时,请使用迁移来更改此函数并返回不同的值。目前无法按操作更改超时。

建议将操作超时设置得尽可能短,以便如果您的应用程序崩溃、意外终止或简单地失去与数据库的连接,它可能持有的任何锁都尽可能快地释放。

默认情况下,操作超时设置为 两分钟

依赖项

~5MB
~100K SLoC