[MDEV-9139] SELECT inside a trigger results in InnoDB gap lock Created: 2015-11-17 Updated: 2018-07-16 Resolved: 2018-07-16 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB, Triggers |
| Affects Version/s: | 10.0.19 |
| Fix Version/s: | N/A |
| Type: | Bug | Priority: | Major |
| Reporter: | Geoff Montee (Inactive) | Assignee: | Jan Lindström (Inactive) |
| Resolution: | Not a Bug | Votes: | 0 |
| Labels: | innodb | ||
| Description |
|
Executing a SELECT and an INSERT inside a trigger seems to require a gap lock, while this gap lock is not needed if the two statements are executed in a transaction outside of the trigger. There might be a good reason for this, but it seems to be undocumented. For example, "trigger" doesn't appear at all on these pages: https://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html https://dev.mysql.com/doc/refman/5.6/en/innodb-record-level-locks.html https://mariadb.com/kb/en/mariadb/xtradbinnodb-lock-modes/ And I don't see this particular locking behavior documented here: https://mariadb.com/kb/en/mariadb/triggers-and-implicit-locks/ First, let's create some tables:
Then let's say that we have the following trigger on test:
And then we execute this:
SHOW ENGINE INNODB STATUS shows that this transaction has a gap lock on the test_log table:
This locking behavior does not appear to be equivalent to the locking behavior of the statements that the transactions run. For example, if we ran the following:
Then SHOW ENGINE INNODB STATUS shows the following:
To get the same locking behavior as the trigger, you have to use a SELECT FOR UPDATE:
Do triggers force SELECT statements to lock like SELECT FOR UPDATE? Is this locking behavior documented somewhere? |
| Comments |
| Comment by Geoff Montee (Inactive) [ 2015-11-25 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Does this trigger require an X gap lock on test_log because a field in test_log is being directly compared to the row in test being updated (i.e. WHERE id = OLD.id)? For example, if the trigger looks like this:
Then it still requires an X gap lock:
But if the trigger looks like this:
Then only an S lock is taken on test_log:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2015-11-26 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Remember that this trigger is BEFORE UPDATE, thus assumption is we make some changes. X lock or gap lock will make sure that result set of that select inside a trigger does not change, now why X-lock, I think this comes from the fact that this is UPDATE trigger. In last example select is based on constant (from InnoDB point of view). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-07-16 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
greenman Can you check the documentation and add a note that UPDATE triggers could acquire gap-locks. |