Skip to main content

数据库事务

¥Database transactions

提醒

这是一个实验性功能,可能会在未来版本中发生变化。

¥This is an experimental feature and is subject to change in future versions.

Strapi 5 提供一个 API 来将一组操作封装在一个事务中,以确保数据的完整性。

¥Strapi 5 provide an API to wrap a set of operations in a transaction that ensures the integrity of data.

事务是一组作为单个单元一起执行的操作。如果任何操作失败,则整个事务失败,数据将回滚到其先前的状态。如果所有操作都成功,则提交事务并将数据永久保存到数据库中。

¥Transactions are a set of operations that are executed together as a single unit. If any of the operations fail, the entire transaction fails and the data is rolled back to its previous state. If all operations succeed, the transaction is committed and the data is permanently saved to the database.

用法

¥Usage

事务通过将处理程序函数传递到 strapi.db.transaction 来处理:

¥Transactions are handled by passing a handler function into strapi.db.transaction:

await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
// It will implicitly use the transaction
await strapi.entityService.create();
await strapi.entityService.create();
});

执行事务处理程序后,如果所有操作都成功,则提交事务。如果任何操作抛出,则回滚事务并将数据恢复到其先前的状态。

¥After the transaction handler is executed, the transaction is committed if all operations succeed. If any of the operations throws, the transaction is rolled back and the data is restored to its previous state.

✏️ 注意

在事务块中执行的每个 strapi.entityServicestrapi.db.query 操作都将隐式使用该事务。

¥Every strapi.entityService or strapi.db.query operation performed in a transaction block will implicitly use the transaction.

事务处理程序属性

¥Transaction handler properties

处理程序函数接收具有以下属性的对象:

¥The handler function receives an object with the following properties:

属性描述
trx事务对象。它可用于在事务中执行 knex 查询。
commit用于提交事务的函数。
rollback用于回滚事务的函数。
onCommit用于注册将在事务提交后执行的回调的函数。
onRollback用于注册将在事务回滚后执行的回调的函数。

嵌套事务

¥Nested transactions

事务可以嵌套。当事务嵌套时,当外部事务提交或回滚时,内部事务也会提交或回滚。

¥Transactions can be nested. When a transaction is nested, the inner transaction is committed or rolled back when the outer transaction is committed or rolled back.

await strapi.db.transaction(async () => {
// It will implicitly use the transaction
await strapi.entityService.create();

// Nested transactions will implicitly use the outer transaction
await strapi.db.transaction(async ({}) => {
await strapi.entityService.create();
});
});

onCommit 和 onRollback

¥onCommit and onRollback

onCommitonRollback 钩子可用于在事务提交或回滚后执行代码。

¥The onCommit and onRollback hooks can be used to execute code after the transaction is committed or rolled back.

await strapi.db.transaction(async ({ onCommit, onRollback }) => {
// It will implicitly use the transaction
await strapi.entityService.create();
await strapi.entityService.create();

onCommit(() => {
// This will be executed after the transaction is committed
});

onRollback(() => {
// This will be executed after the transaction is rolled back
});
});

使用 knex 查询

¥Using knex queries

事务也可以与 knex 查询一起使用,但在这些情况下必须明确调用 .transacting(trx)

¥Transactions can also be used with knex queries, but in those cases .transacting(trx) must be explicitly called.

await strapi.db.transaction(async ({ trx, rollback, commit }) => {
await knex('users').where('id', 1).update({ name: 'foo' }).transacting(trx);
});

何时使用事务

¥When to use transactions

在多个操作应一起执行且它们的执行相互依赖的情况下,应使用事务。例如,在创建新用户时,应在数据库中创建该用户,并向该用户发送欢迎电子邮件。如果电子邮件发送失败,则不应在数据库中创建用户。

¥Transactions should be used in cases where multiple operations should be executed together and their execution is dependent on each other. For example, when creating a new user, the user should be created in the database and a welcome email should be sent to the user. If the email fails to send, the user should not be created in the database.

何时不使用事务

¥When not to use transactions

事务不应用于不相互依赖的操作,因为它可能导致性能损失。

¥Transactions should not be used for operations that are not dependent on each other since it can result in performance penalties.

事务的潜在问题

¥Potential problems of transactions

在事务内执行多个操作可能会导致锁定,这可能会阻止其他进程执行事务,直到原始事务完成。

¥Performing multiple operations within a transaction can lead to locking, which can block the execution of transactions from other processes until the original transaction is complete.

此外,如果事务未正确提交或回滚,则可能会停滞。

¥Furthermore, transactions can stall if they are not committed or rolled back appropriately.

例如,如果打开了事务,但代码中有一个路径没有关闭它,则事务将无限期保持打开状态,并可能导致不稳定,直到重新启动服务器并强制关闭连接。这些问题可能难以调试,因此在必要时请谨慎使用事务。

¥For example, if a transaction is opened but there is a path in your code that does not close it, the transaction will be left open indefinitely and could cause instability until your server is restarted and the connection is forced to close. These issues can be difficult to debug, so use transactions with care in the cases they are necessary.