Bug #20134 | deadlock with DELETE/INSERT | ||
---|---|---|---|
Submitted: | 30 May 2006 4:10 | Modified: | 14 Jun 2006 15:26 |
Reporter: | Bradley Baetz | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
Version: | 4.1.19 | OS: | Linux (RHEL4) |
Assigned to: | CPU Architecture: | Any |
[30 May 2006 4:10]
Bradley Baetz
[30 May 2006 4:57]
Valeriy Kravchuk
Thank you for a detailed problem report. Sorry, but it looks like a result of documented "next key locking" algorithm (http://dev.mysql.com/doc/refman/4.1/en/innodb-next-key-locking.html): "When InnoDB scans an index, it can also lock the gap after the last record in the index. Just that happens in the previous example: The locks set by InnoDB prevent any insert to the table where id would be bigger than 100."
[30 May 2006 5:29]
Bradley Baetz
Sure, but I don't have a problem with the lock. The problem is that this is being detected as a deadlock. I'd be happy with one of the queries blocking (well, not happy, but... ;) If I use SELECT * FROM foo WHERE user_id > 1 FOR UPDATE instead of the delete, there isn't any deadlock, so theres something different then that page. This happens under any transaction isolation mode, so its not a side effect of the transaction being serializable.
[30 May 2006 5:59]
Bradley Baetz
innodb_locks_unsafe_for_binlog makes this go away, but since I'm also using replication that doesn't help... However, if the highest isolation mode used is READ COMMITTED (which it is for me), would replication still be unsafe?
[14 Jun 2006 15:26]
Valeriy Kravchuk
I think, manual explains it all in enough details. Read http://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html, for example: "- innodb_locks_unsafe_for_binlog This variable controls next-key locking in InnoDB searches and index scans. By default, this variable is 0 (disabled), which means that next-key locking is enabled. Normally, InnoDB uses an algorithm called next-key locking. InnoDB performs row-level locking in such a way that when it searches or scans a table index, it sets shared or exclusive locks on any index records it encounters. Thus, the row-level locks are actually index record locks. The locks that InnoDB sets on index records also affect the “gap” preceding that index record. If a user has a shared or exclusive lock on record R in an index, another user cannot insert a new index record immediately before R in the order of the index. Enabling this variable causes InnoDB not to use next-key locking in searches or index scans. Next-key locking is still used to ensure foreign key constraints and duplicate key checking. Note that enabling this variable may cause phantom problems: Suppose that you want to read and lock all children from the child table with an identifier value larger than 100, with the intention of updating some column in the selected rows later: SELECT * FROM child WHERE id > 100 FOR UPDATE; Suppose that there is an index on the id column. The query scans that index starting from the first record where id is larger than 100. If the locks set on the index records do not lock out inserts made in the gaps, another client can insert a new row into the table. If you execute the same SELECT within the same transaction, you see a new row in the result set returned by the query. This also means that if new items are added to the database, InnoDB does not guarantee serializability Therefore, if this variable is enabled InnoDB guarantees at most isolation level READ COMMITTED. (Conflict serializability is still guaranteed.) This variable is available as of MySQL 4.1.4." You need to serialize actions to replicate them properly with the same results. I am closing this report as not a bug. All these is intended and documented behaviour.