[MDEV-12004] InnoDB wrongly thinks that a column is indexed after failed ADD UNIQUE INDEX Created: 2017-02-06 Updated: 2019-04-26 Resolved: 2017-02-07 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB, Virtual Columns |
| Affects Version/s: | 10.2.3 |
| Fix Version/s: | 10.2.4 |
| Type: | Bug | Priority: | Major |
| Reporter: | Elena Stepanova | Assignee: | Marko Mäkelä |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | 10.2-ga | ||
| Description |
|
|
| Comments |
| Comment by Marko Mäkelä [ 2017-02-07 ] | ||||||||||||||||||||||||||||||||||
|
The problem appears to be that the dict_v_col_t::v_indexes is inconsistent with the table definition. It should have been emptied when the ALTER TABLE operation was rolled back. After crash recovery, the table is empty, consisting of an empty clustered index root page with PAGE_INDEX_ID 0x15. There is no secondary index. In SYS_INDEXES, the last record is (TABLE_ID=0x14,ID=0x15,DB_TRX_ID=0x509,DB_ROLL_PTR=(insert),NAME='GEN_CLUST_INDEX',N_FIELDS=0,TYPE=DICT_CLUSTERED,SPACE=4,PAGE_NO=3,MERGE_THRESHOLD=50). So, it seems that the ALTER TABLE must have returned ER_DUP_ENTRY, and then TRUNCATE TABLE must have emptied the table. With a DEBUG_SYNC on inplace_after_index_build, I verified that the TRUNCATE is blocked until ha_innobase::inplace_alter_table() returns control to the SQL layer. TRUNCATE should still be blocked while ha_innobase::commit_inplace_alter_table() is executing, to roll back the failed ALTER TABLE operation. Actually it turns out that mysql_alter_table() must return before TRUNCATE TABLE can continue:
The two last Note were produced by a patch:
Furthermore, in the TRUNCATE, we have only the clustered index in the table, and table->drop_aborted=FALSE. I cannot see any fixes to this between MySQL 5.7.14 (which has been merged to MariaDB Server 10.2) and the currently latest published release 5.7.17. So, I guess that MySQL 5.7 should be affected as well. If the TRUNCATE TABLE is replaced with DELETE FROM, there is no crash. | ||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-02-07 ] | ||||||||||||||||||||||||||||||||||
|
Actually the dict_v_col_t::v_indexes is empty as it should, but the problem is that dict_col_t::ord_part is not always cleared. There is a loop in rollback_inplace_alter_table() that tries to clear the flag. However, check_col_exists_in_indexes(prebuilt->table, i, true) sometimes holds when it should not. The fix is that in rollback_inplace_alter_table(), we must only consider committed indexes when determining the appropriate state of the ord_part flag. | ||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-02-07 ] | ||||||||||||||||||||||||||||||||||
|
http://lists.askmonty.org/pipermail/commits/2017-February/010624.html | ||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2017-02-07 ] | ||||||||||||||||||||||||||||||||||
|
ok to push. |