Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/other-topics/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,84 @@ const sequelize = new Sequelize('sqlite::memory:', {

**Note for MSSQL:** _The `SET ISOLATION LEVEL` queries are not logged since the specified `isolationLevel` is passed directly to `tedious`._

## Manually retrying failed transactions

Sequelize does not automically retries on potential write conflicts or deadlocks, when using a certain level of isolations, it is expected that transactions may fail due to potential write conflicts in concurrent transactions or deadlocks.

You can programmatically fix this by relying on options from the [retry-as-promised](https://github.com/mickhansen/retry-as-promised/blob/master/README.md) library:

```typescript
const { Sequelize } = require('@sequelize/core');

const sequelize = new Sequelize(process.env.DB_NAME,
process.env.DB_NAME,
process.env.DB_PASS,
{
host: process.env.DB_HOST,
dialect: 'mysql',
// Here:
retry: {
max: 3, // this may cause memory leaks if you set the retries limit too much.
match: [
Sequelize.ConnectionError,
Sequelize.ConnectionRefusedError,
Sequelize.ConnectionTimedOutError,
Sequelize.OptimisticLockError,
Sequelize.TimeoutError,
/Deadlock/i, // retry-as-promised also takes RegExp, for example to find deadlocks error.
],
}
});
```

You can use other possible error classes [here](https://sequelize.org/api/v7/classes/error).

List of the default retry options and the value when you passing `{}` to the retry option:

```js
{
retry: {
$current: 1,
max: undefined,
timeout: undefined,
match: [],
backoffBase: 100,
backoffExponent: 1.1,
report: function () {},
name: 'unknown',
}
}
```

You can also fix this without relying on options from the `retry-as-promised` library:

```typescript
const { Sequelize, Transaction } = require('@sequelize/core');

async function executeSomething() {
const MAX_RETRIES = 5;
let retriesCount = 0;

let result;
while (retriesCount < MAX_RETRIES) {
try {
result = await sequelize.transaction({
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
}, async (t) => {
// Your code
});
} catch (error) {
// You can modify the script below to achieve your goals.
if (error.message === 'the error message') {
retriesCount++;
continue;
}
throw error;
}
}
}
```

## Usage with other sequelize methods

The `transaction` option goes with most other options, which are usually the first argument of a method.
Expand Down