> For the complete documentation index, see [llms.txt](https://mariadb.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mariadb.com/docs/server/reference/error-codes/mariadb-error-codes-1000-to-1099/e1020.md).

# Error 1020: Record has changed since last read in table

| Error Code | SQLSTATE | Error         | Description                                                                  |
| ---------- | -------- | ------------- | ---------------------------------------------------------------------------- |
| 1020       | HY000    | ER\_CHECKREAD | Record has changed since last read in table '%s'; try restarting transaction |

## Possible Causes and Solutions

With InnoDB tables, the server returns this error when a transaction tries to change or lock a row that another transaction has changed and committed since the first transaction took its snapshot. InnoDB detects this only when [innodb\_snapshot\_isolation](/docs/server/server-usage/storage-engines/innodb/innodb-system-variables.md#innodb_snapshot_isolation) is `ON`, and only at the [REPEATABLE READ](/docs/server/reference/sql-statements/transactions/transactions-repeatable-read.md) and [SERIALIZABLE](/docs/server/reference/sql-statements/transactions/transactions-serializable.md) isolation levels. `REPEATABLE READ` is the default isolation level.

{% hint style="info" %}
`innodb_snapshot_isolation` is `ON` by default from MariaDB 11.8, and `OFF` by default in MariaDB 10.6, 10.11 and 11.4. So applications often see this error for the first time after an upgrade to MariaDB 11.8 or later. See [Upgrading from MariaDB 11.4 to MariaDB 11.8](/docs/server/server-management/install-and-upgrade-mariadb/upgrading/mariadb-community-server-upgrade-paths/upgrading-from-mariadb-11-4-to-mariadb-11-8.md).
{% endhint %}

For example, the first session reads a row, a second session changes it, and then the first session tries to change it, too:

```sql
-- Session 1
START TRANSACTION;
SELECT balance FROM acct WHERE id=1;

-- Session 2
UPDATE acct SET balance=balance+50 WHERE id=1;

-- Session 1
UPDATE acct SET balance=balance-10 WHERE id=1;
ERROR 1020 (HY000): Record has changed since last read in table 'acct'; try restarting transaction
```

Without this check, session 1 would change the row based on a balance it read before session 2's change, which is known as a lost update.

**InnoDB rolls back the whole transaction**, not only the failed statement, as it does for a [deadlock](/docs/server/reference/error-codes/mariadb-error-codes-1200-to-1299/e1213.md). All earlier changes of the transaction are gone, and the session is no longer in a transaction.

To solve the error:

* Retry the whole transaction from its start, as for a deadlock. The retry takes a new snapshot and sees the other transaction's change.
* If the transaction reads rows that it changes later, read them with [SELECT ... FOR UPDATE](/docs/server/reference/sql-statements/data-manipulation/selecting-data/for-update.md). That locks the rows when they're read, so the other transaction waits instead of changing them first.
* If the application doesn't depend on a consistent snapshot, use the [READ COMMITTED](/docs/server/reference/sql-statements/transactions/transactions-read-committed.md) isolation level, where each statement sees the latest committed data.
* `SET SESSION innodb_snapshot_isolation=OFF` restores the behavior of older versions. The `UPDATE` then works on the latest committed version of the row, which the transaction's earlier reads didn't see.

{% hint style="info" %}
From MariaDB 10.11.17, 11.4.11, 11.8.7 and 12.3.2, the message ends with `; try restarting transaction` ([MDEV-39264](https://jira.mariadb.org/browse/MDEV-39264)). In MariaDB 10.6, it ends after the table name.
{% endhint %}

Unlike this error, a [lock wait timeout](/docs/server/reference/error-codes/mariadb-error-codes-1200-to-1299/e1205.md) rolls back only the statement, unless [innodb\_rollback\_on\_timeout](/docs/server/server-usage/storage-engines/innodb/innodb-system-variables.md#innodb_rollback_on_timeout) is set.

<sub>*This page is licensed: CC BY-SA / Gnu FDL*</sub>

{% @marketo/form formId="4316" %}
