[MDEV-13359] Enable online ALTER TABLE for compressed columns Created: 2017-07-20 Updated: 2017-09-13 Resolved: 2017-09-01 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Affects Version/s: | 10.3 |
| Fix Version/s: | 10.3.2 |
| Type: | Bug | Priority: | Major |
| Reporter: | Sergey Vojtovich | Assignee: | Marko Mäkelä |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||||||||||||||
| Description |
|
!!! PLEASE DO NOT CHANGE OBJECTIVE OF THIS BUG AND DON'T CLOSE IT UNTIL DESCRIBED PROBLEM IS SOLVED !!! Apparently InnoDB doesn't copy blob data during online ALTER TABLE. In a meanwhile it calls innobase_rec_reset(), which may reallocate memory for blobs. It wasn't a problem before column compression was introduced, since in most (if not all) cases memory reallocation was not needed. With compressed columns reallocation is always there. To reproduce this issue grep for Objective of this bug is to enable online ALTER TABLE for compressed columns. |
| Comments |
| Comment by Marko Mäkelä [ 2017-08-07 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
InnoDB does copy BLOB data ALTER TABLE…ALGORITHM=INPLACE, LOCK=NONE. For ADD INDEX (adding secondary indexes that include column prefixes of BLOB columns), the BLOB prefixes are copied already when creating the secondary index entries in row0merge.cc. For table-rebuilding online ALTER, entire BLOBs are copied in two places: when initially building the new clustered index in row_merge_insert_index_tuples(), or later in row_log_table_apply_convert_mrec(). The latter operation is protected by index->online_log->blobs, which keeps track of freed BLOB objects, so that if purge or rollback is freeing BLOBs during the log apply, we will avoid dereferencing dangling blob pointers. svoj, what exactly do you mean by saying that blob data is not being copied? Please note that innobase_rec_reset() and innobase_row_to_mysql() are only used for reporting duplicate key errors. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergey Vojtovich [ 2017-08-25 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I confirm the problem is still there, in 10.3 with Rebased version of column compression is currently in bb-10.3- Test case:
It should work pretty well, now apply the following patch:
Works fine still, now revert InnoDB workaround:
Now it either fails with "1259: ZLIB: Input data corrupted" or crashes with:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-08-28 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
InnoDB only calls the innobase_rec_reset() to ensure that when a duplicate key error is reported, the error message will not contain bogus values for columns whose values are unknown.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergey Vojtovich [ 2017-08-28 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I haven't tested it.
I don't understand this question. Did you mean life time? Value is there until it is updated, in this case it gets updated by innobase_rec_reset().
Fine with me, assuming it doesn't use same record[] for in/out.
Conflict with what? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergey Vojtovich [ 2017-08-28 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Note that I can be very wrong about innobase_rec_reset() being culprit. Last time I debugged it was about half year ago. Tencent also came across this issue in their implementation and they had to disable it. Probably for different reason though. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-01 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The fix is to simply remove the function innobase_rec_reset(). I had introduced this function in the InnoDB Plugin for MySQL 5.1, which later evolved into MySQL 5.5. There used to be a bug that ADD UNIQUE INDEX would not always correctly report the duplicate key value of the secondary index. This function ensured that instead of reporting totally garbage values, InnoDB would report column default values. It looks like I made the function unnecessary in MySQL 5.6.6 and adjusted the test. Now that the InnoDB ALTER TABLE tests were imported as part of The unnecessary function did not do any harm before One question remains: What if we needed to report a duplicate key value for a compressed column? The simple answer is that the test main.column_compression demonstrates that no indexes can be defined on compressed columns. |