Commit graph

199175 commits

Author SHA1 Message Date
Nikita Malyavin
30c965f866 MDEV-31777 ER_GET_ERRNO upon online alter on CONNECT table
Forbid Online for CONNECT.
2023-08-15 14:00:28 +02:00
Nikita Malyavin
44ca37ef17 MDEV-31631 Adding auto-increment to table with history online misbehaves
Adding an auto_increment column online leads to an undefined behavior.
Basically any DEFAULTs that depend on a row order in the table, or on
the non-deterministic (in scope of the ALTER TABLE statement) function
is UB.

For example, NOW() is considered generally non-deterministic
(Item_func_now_utc is marked with VCOL_NON_DETERMINISTIC), but it's fixed
in scope of a single statement.

Same for any other function that depends only on the session/status vars
apart from its arguments.

Only two UB cases are known:
* adding new AUTO_INCREMENT column. Modifying the existing column may be
fine under certain circumstances, see MDEV-31058.
* adding new column with DEFAULT(nextval(...)). Modifying the existing
column is possible, since its value will be always present in the online
event, except for the NULL -> NOT NULL modification
2023-08-15 14:00:28 +02:00
Nikita Malyavin
e026a366bf MDEV-31776 Online ALTER reports the number of affected rows incorrectly
Add a new virtual function that will increase the inserted rows count
for the insert log event and decrease it for the delete event.

Reuses Rows_log_event::m_row_count on the replication side, which was only
set on the logging side.
2023-08-15 14:00:28 +02:00
Nikita Malyavin
9c8554259a MDEV-31775 Server crash upon online alter on sequence
Forbid online for sequences. It doesn't work now and sequence tables are
always only one row, so not worth the extra complexity.
2023-08-15 14:00:28 +02:00
Nikita Malyavin
7d0d9eab03 add to binlog_bytes_written for an initial description event 2023-08-15 14:00:28 +02:00
Nikita Malyavin
2952274ac4 make a proper cleanup if online_alter_binlog is failed to create 2023-08-15 14:00:28 +02:00
Andrei
bac8f189ed MDEV-31755 Replica's DML event deadlocks wit online alter table
The deadlock was caused by too strong MDL acquired by the start ALTER.

Replica's ALTER TABLE replication consists of two phases:
1. Start ALTER (SA) -- the event is emittd in the very beginning,
allowing replication start ALTER in parallel
2. Commit ALTER (CA) -- ensures that master finishes successfully

CA is normally received by wait_for_master call.
If parallel DML was run, the following sequence will take place:

|- SA
|- DML
|- CA

If CA is handled after MDL upgrade, it'll will deadlock with DML.

While MDL is shared by the start ALTER wait for its 2nd part
to allow concurrent DMLs to grab the lock.

The fix uses wait_for_master reentrancy -- no need to avoid a second call
in the end of mysql_alter_table.

Since SA and CA are marked with FL_DDL, the DML issued in-between cannot be
rescheduled before or after them. However, SA "commits" (by he call of
write_bin_log_start_alter and, subsequently,
thd->wakeup_subsequent_commits) before the copy stage begins, unlocking
the DMLs to run on this table. That is, these DMLs will be executed
concurrently with the copy stage, making Online alter effective on replicas
as well

Co-authored-by: Nikita Malyavin (nikitamalyavin@gmail.com)
2023-08-15 14:00:28 +02:00
Nikita Malyavin
e1b9ab1995 fix key detection on replica with extra columns 2023-08-15 14:00:28 +02:00
Nikita Malyavin
70491fb07b MDEV-31677 Assertion failed upon online ALTER with binlog_row_image=NOBLOB
Make binlog_prepare_row_images accept image type as an argument.
2023-08-15 14:00:28 +02:00
Nikita Malyavin
a539fac8bd MDEV-31646 untie from max_allowed_packet and opt_binlog_rows_event_max_size 2023-08-15 14:00:28 +02:00
Nikita Malyavin
d5e59c983f MDEV-31646 Online alter applies binlog cache limit to cache writes
1. Make online disk writes unlimited, same as filesort does.
2. Make proper error handling -- in 32-bit build IO_CACHE capacity limit is
4GB, so it is quite possible to overfill there.
3. Event_log::write_cache complicated with event reparsing, and as it was
proven by QA, contains some mistakes. Rewrite introbuce a simpler and much
faster version, not featuring reparsing and therefore copying a whole
buffer at once. This also disables checksums and crypto.
4. Handle read_log_event errors correctly: error returned is -1 (eof
signal for alter table), and my_error is not called. Call my_error and
always return 1. There's no test for this, since it shouldn't happen,
see the next bullet.
5. An event could be written partially in case of error, if it's bigger
than the IO_CACHE buffer. Restore the position where it was before the
error was emitted.

As a result, online alter is untied of several binlog variables, which was
a second aim of this patch.
2023-08-15 13:59:07 +02:00
Marko Mäkelä
b4ace139a1 Remove the often-hanging test innodb.alter_rename_files
The test innodb.alter_rename_files rather frequently hangs in
checkpoint_set_now. The test was removed in MariaDB Server 10.5
commit 37e7bde12a when the code that
it aimed to cover was simplified. Starting with MariaDB Server 10.5
the page flushing and log checkpointing is much simpler, handled
by the single buf_flush_page_cleaner() thread.

Let us remove the test to avoid occasional failures. We are not going
to fix the cause of the failure in MariaDB Server 10.4.
2023-08-15 12:14:31 +03:00
Marko Mäkelä
5f6e987481 Merge 10.11 into 11.0 2023-08-15 12:02:07 +03:00
Marko Mäkelä
39b0c2b82a MariaDB 11.0.3 release
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEF39AEP5WyjM2MAMF8WVvJMdM0dgFAmTaWhMACgkQ8WVvJMdM
 0dhNlw//XGTmm+FtGS4XeKYdxOobqG0NowyV9/Gcb7B3wBJo9qm2X73q7ESkQtvQ
 st76bNVqriuyg8fYnbWiCN3pPkfZ008f7AMk89h3RRfKMYyQRFqaUUjfUmB2uYxz
 oa1BcwunRclh7cveE20EVISFVBmol2IkTCU16F5RCW6vHN3mO81U1yjkaIbUSpsB
 O7ZjreQ79cx+I0RxbzGnsJj0BFxFLRghxOL5ZqRW/QpLMrirvyeW89vumgLe/hL6
 pYd+S+RvCJjAcbOPaQE+xuQ+BI5vaqQjlt39OY6A3o1jEyGFIDizJMFogFHTwhkR
 0bAsGeJwsyD9xBQAXC9vKcAF7GDdZTA1kNryrAYEg/YeCUZm+wxE7OLMtAsIhf98
 o73OQgeYjdOe/t2yy9CYAox5UVzKzYdvwpeiA0DqVOLHIpF8wS6J3lw+WPuieqfI
 CuYrbw4weeSECpYjd5eo0iuagQqgA+rFY3yfvj8lnlv+2xE70J4eCtmD/wWBgCyu
 SfP9HFMDIFYt83vhwHfTpt/iryv+dheT4fDf+KTpQt66VLgEd+mVt9QZpSqy08rK
 f/KpETQF8YCQMWu0cKkZz8/vtcxaakIxN9+uZLIG0GwCORFGPWvKJfAdCYBnBN5x
 B/15bS6HKZeRMMErTOhCsLd/h0XRWHQAt6GdapNfgqwd9ZmZC/8=
 =VtP/
 -----END PGP SIGNATURE-----

Merge mariadb-11.0.3 into 11.0
2023-08-15 12:01:23 +03:00
Marko Mäkelä
acc90ce363 Merge 10.10 into 10.11 2023-08-15 11:24:41 +03:00
Marko Mäkelä
00d315a1b1 MariaDB 10.11.5 release
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEF39AEP5WyjM2MAMF8WVvJMdM0dgFAmTaWdkACgkQ8WVvJMdM
 0djgRQ/+PxULklYgBnlw004qdxIzHdexs+HZkU63BxAFzUgEc/1As+vSxByG7b9p
 mD3Q43HE5NuxDV2bfEnyYSz+DIJemz/7AkCzBQg0l1Hx6q3j5fJ34dGT5mDWQOZ4
 sS92vIV1LGF0to09UYkambZLUTHbIjKsniIaDiwgQDDbNncMyGNRP6MyzB6x8YM2
 0NgQ4Jwg3QacneABsLy6UEGq8Wg1dTgNoH8w5YgvV3zFoWZPCFQJYMVEv4QUlMjd
 f4Pj0VaERwqTDvgd6MaFO88IdMo/7+alSQeIOJcgG2qsQXm1DbNmrXNpchOTLLdR
 ksUB5yjw8tDdPvKU3xDmry8IWDfUc2Sw+j5d8Qgwaxw63CJy+Bfp0IIdVhzSjBT4
 xmOuSPME2/Z7/yTVt23XCe4isiurg06WBeWe/bm3nr31W1XPC3a89SFy6zMjscKz
 +HtkzywSrh1AHW7ma3XrqCEtX/u4D+qxQEbK2QMVXt26Q+m4ZylXX4XAgu9dBon8
 UiAsgYWfapOHuoY2rz1yomx49EcuFZ6EHqrZzWlyBUIKAxasezAwAsJ/7fiTuoaw
 7eLqiNEGqh/I3eE3iFCebrW0W/TSeDFLx4CPkuxNRUaFKQSp3EtwAMTbIqH5bVNG
 1psFJEcJYG0KMSXXxtH5jlLO8bzGdlJ124ExBZ/MV62GxJQ8UBY=
 =kZoB
 -----END PGP SIGNATURE-----

Merge mariadb-10.11.5 into 10.11
2023-08-15 11:24:02 +03:00
Marko Mäkelä
17f5f1cba9 Merge 10.6 into 10.10 2023-08-15 11:22:36 +03:00
Marko Mäkelä
3fee1b4471 Merge 10.5 into 10.6 2023-08-15 11:21:34 +03:00
Nikita Malyavin
2cecb5a638 MDEV-31601 Some ALTER TABLEs fail ... with a wrong error message
Report correct algorithm in the error message.
2023-08-15 10:16:14 +02:00
Nikita Malyavin
8a165d7c19 follow-up MDEV-30430: fix versioning.rpl
Don't skip row_end if it wasn't set explicitly.

Also another segfault was caused by accessing rpl_write_set on slave during
the row update/delete.
The reason was a default_column_bitmaps() call, which also sets
rpl_write_set to NULL.
Previously, the related behavior was changed in commit afd3ee97ad, where
one such call was removed from Update_rows_log_event::do_exec_row, but the
same one was mistakenly left in Delete_rows_log_event. Now it's also
removed.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
43cb98b420 fix main.mysql57_virtual, main.alter_table, innodb.alter_algorithm
The correct (best) algorithm is now chosen for ALGORITHM=DEFAULT
and alter_algorithm=DEFAULT

See also MDEV-30906
2023-08-15 10:16:13 +02:00
Nikita Malyavin
c382de72ea MDEV-30984 Online ALTER table is denied with non-informative error messages
Group all the checks in online_alter_check_supported().

There is now two groups of checks:
1. A technical availability of online, that is checked before open_tables,
and affects table_list->lock_type. It's supposed to be safe to make it
TL_READ even if COPY algorithm will fall back to not-online, since MDL is
SHARED_UPGRADEABLE anyway.
2. An 'online' availability for a COPY algorithm. It can be done as late as
just before the copy_data_between_tables call. The lock_type influence is
disclosed above, so the only other place it affects is
Alter_info::supports_lock, where `online` flag is only used to decide
whether to report the error at the inplace preparation stage. We'd want to
make that at the last resort, which is COPY preparation, if no algorithm is
chosen by the user. So it's event better now.

Some changes are required to the autoinc support detection, as the check
now happens after mysql_prepare_alter_table:
* alter_info->drop_list is empty
* instead, dropped columns are in tmp_set
* alter_info->create_list now has every field that's in the new table.
* the column definition's change.str will be nonnull whether the column
  remains in the new table (vs whether it was changed, as before).
  But it also has `field` field set.
* IF EXISTS doesn't have to be dealt anymore

This infers that the changes are now checked in more detail: a field's
definition shouldn't be changed, vs a field shouldn't be mentioned in
the CHANGE list, as it was before. This is reflected by the line 193 test.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
b3f988d260 Add const to get_foreign_key_list/get_parent_foreign_key_list 2023-08-15 10:16:13 +02:00
Nikita Malyavin
500787c72a Add const to alloc-related thd methods
Also update abi declarations. The abi itself is unchanged, since const
doesn't affect C-style exported name.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
d7b0c6d8a8 MDEV-30987 main.alter_table_online times out with view-protocol
disabie view-protocol for certain places:
1. While a transaction is in progress: a view gets locked for a
transaction duration, so DROP VIEW from a servicing conneciton
deadlocks. We can't just disable servicing connection, as
CREATE VIEW and DROP VIEW commit implicitly.
2. For querying Opened_table_definitions: the actual query executed
is `SELECT * FROM mysqltest_tmp_v`, then the view is dropped
2023-08-15 10:16:13 +02:00
Nikita Malyavin
55d1645d5b MDEV-31059 "Slave SQL" errors upon concurrent DML and erroneous ALTER
Skip more rpl-related error handling.
Also move the error check inside if (table) -- otherwise the error
should be handled already.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
3a42f2869e refactor unpack_row
Online alter and replication paths differ quite noticeably. It's time to
fix the mess. Online alter has to unpack the old table's data
(here conv_table), and then convert, while replication requires more
sophisticated track: handle possible conversions, treat extra replica
fields, and carefully deduce master's record length.

* Extract unpack_field.
* handle the unpacking progress through a state machine presented by
  Unpack_record_state struct.
* Stick most of the online alter unpacking together under a single
  conditional branch.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
500379cf49 unpack_row: unpack a correct number of fields 2023-08-15 10:16:13 +02:00
Nikita Malyavin
da277396bd MDEV-31058 ER_KEY_NOT_FOUND upon concurrent CHANGE column autoinc and DML
When column is changed to autoinc, ALTER TABLE may update zero/NULL values,
if NO_AUTO_VALUE_ON_ZERO mode is not enabled.

Forbid this for LOCK=NONE for the unreliable cases.
The cases are described in online_alter_check_autoinc.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
af82d56a51 unpack_row: set the correct fields in has_value_set for online alter 2023-08-15 10:16:13 +02:00
Nikita Malyavin
ecb9db4c3d MDEV-30949 Direct leak in binlog_online_alter_end_trans
when committing a big transaction, online_alter_cache_log creates a cache
file. It wasn't properly closed, which was spotted by a memory leak from
my_register_filename. A temporary file also remained open.

Binlog wasn't affected by this, since it features its own file management.

A proper closing is calling close_cached_file. It deinits io_cache and
closes the underlying file. After closing, the file is expected to be
deleted automagically.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
0695f7dd7b MDEV-31043 ER_KEY_NOT_FOUND upon concurrent ALTER and transaction
Non-transactional engines changes are visible immediately the row operation
succeeds, so we should apply the changes to the online buffer immediately
after the statement ends.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
c76072db93 MDEV-31033 ER_KEY_NOT_FOUND upon online COPY ALTER on a partitioned table
The row events were applied "twice": once for the ha_partition, and one
more time for the underlying storage engine.

There's no such problem in binlog/rpl, because ha_partiton::row_logging
is normally set to false.

The fix makes the events replicate only when the handler is a root handler.
We will try to *guess* this by comparing it to table->file. The same
approach is used in the MDEV-21540 fix, 231feabd. The assumption is made,
that the row methods are only called for table->file (and never for a
cloned handler), hence the assertions are added in ha_innobase and
ha_myisam to make sure that this is true at least for those engines

Also closes MDEV-31040, however the test is not included, since we have no
convenient way to construct a deterministic version.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
0775c7bdc3 MDEV-30945 RPL tests are failing with MSAN use-of-uninitialized-value
...in bitmap_intersect

m_cols_ai was accessed during the Delete event, however this field is only
related to Updates.

Moving it to Update_rows_event would require too much effort. So instead:
* Only access m_cols_ai in Update events (conditional branch is added in
  Rows_log_event::do_add_row_data)
* Clean up m_cols_ai operations in Rows_log_event constructor.
  m_cols_ai.bitmap is first set to NULL, indicating invalid event.
  Then it is initialized:
  -> For Update events, a new bitmap is created.
  -> For other events, debug mode, m_cols_ai.bitmap is set to 1, indicating
     that the value is correct, but it shouldn't be accessed. To make sure
     we'll have a failure, n_bits is also set to 1.
  -> In release mode, m_cols_ai mirrors m_cols, providing extra safety
     in production.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
2ce2440538 clean up Rows_log_event virtual methods
Modernize declaration to C++11.
Add missing const.
Convert TYPE_CODE to constexpr.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
e1f5c58ac7 MDEV-30891 Assertion `!table->versioned(VERS_TRX_ID)' failed
Assertion `!table->versioned(VERS_TRX_ID)' failed in
Write_rows_log_event::binlog_row_logging_function during ONLINE ALTER.

trxid-versioned tables can't be replicated.
ONLINE ALTER will also be forbidden for these tables.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
5361b87093 add partition test 2023-08-15 10:16:13 +02:00
Nikita Malyavin
5f206259e5 MDEV-30985 Replica stops with error on ALTER ONLINE with Geometry Types
The bug is inherent for row-based replication as well.
To reproduce, a virtual (not stored) field of a blob type computed from
another field of a different blob type is required.

The following happens during an update or delete row event:
1. A row is unpacked.
2. Virtual fields are updated. Field b1 stores the pointer in
   Field_blob::value and references it in table->record[0].
3. record[0] is stored to record[1] in Rows_log_event::find_row.
4. A new record is fetched from handler. (e.g. ha_rnd_next)
5. Virtual columns are updated (only non-stored).
6. Field b1 receives new value. Old value is deallocated
   (Field_blob::val_str).
7. record_compare is called. record[0] and record[1] are compared.
8. record[1] contains a reference to a freed value.

record_compare is used in replication to find a matching record for update
or delete. Virtual columns that are not stored should be definitely skipped
both for correctness, and for this bug fix.

STORED virtual columns, on the other hand, may be required and shouldn't be
skipped. Stored columns are not affected, since they are not updated after
handler's fetch.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
3ad0e7edd1 MDEV-30924 Server crashes in MYSQL_LOG::is_open upon ALTER vs FUNCTION
ASAN showed use-after-free in binlog_online_alter_end_trans, during
running through thd->online_alter_cache_list.

In online_alter_binlog_get_cache_data, new_cache_data was allocated on
thd->mem_root, in case of autocommit=1, but this mem_root could be freed
in sp_head::execute, upon using stored functions.

It appears that thd->transaction->mem_root exists even in single-stmt
transaction mode (i.e autocommit=1), so it can be used in all cases.
This mem_root will remain valid till the end of transaction, including
commit phase.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
6b35d6a909 MDEV-30925 Assertion failed in translog_write_record in ONLINE ALTER + Aria
This is the corner case of ONLINE ALTER vs ha_maria vs App-time Periods.

When a Delete_rows_event (or update) is executed, a lookup handler may be
created, normally to serve long unique index needs, by a call of
handler::prepare_for_insert. This function also creates a lookup handler
if an application-time period exists in a table.

A difference with a usual call of prepare_for_insert is that transactions
are disabled for this table during ALTER TABLE. See
mysql_trans_prepare_alter_copy_data call in copy_data_between_tables.

Then, ha_maria calls _ma_tmp_disable_logging_for_table during
ha_maria::external_lock. It never happened so before, that two handlers
would be created for write to a single ha_maria table under transactions
disabled.

Hence, the fix handles this scenario.
It could be done otherwise, by not creating this lookup handler (since it's
not used anyway during ONLINE ALTER), but architecturally, two handlers
should be supported.

Avoiding the creation of lookup handler could be done here additionally,
but with a cost of slowing down other more generic cases, with an
additional check of online alter table active.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
6f78efc01c MDEV-30902 Server crash in LEX::first_lists_tables_same
ONLINE ALTER TABLE uses binlog events like the replication does.

Before it was never used outside of replication, so significant
change was required. For example, a single event had a statement-like
befavior: it locked the tables, opened it, and closed them in the end. But
for ONLINE ALTER we use preopened table.

A crash scenario is following: lex->query_tables was set to NULL in
restore_empty_query_table_list when alter event is applied.
Then lex->query_tables->prev_global was write-accessed in
LEX::first_lists_tables_same, leading to a segfault.

In replication restore_empty_query_table_list would mean resetting lex
before next query or event.

In ONLINE ALTER TABLE we reuse a locked table between the events, so
we should avoid it. Here the need to reset lex state (or close the tables)
can be determined by nonzero rgi->tables_to_lock_count.
If no table is locked, then event doesn't own the tables.

The same was already done before for rgi->slave_close_thread_tables call.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
b08b78c5b9 MDEV-29068 Cascade foreign key updates do not apply in online alter 2023-08-15 10:16:13 +02:00
Nikita Malyavin
84ed2e7ce6 fix main.alter_table_{online,lock} 2023-08-15 10:16:13 +02:00
Nikita Malyavin
41697008fe MDEV-29069 follow-up: improve DEFAULT rules
previously, fields with DEFAULTs were allowed just when expression is
deterministic. In case of online alter, we should recursively check that
underlying fields of expression also either have explicit values, or
have DEFAULT following this validity rule.
2023-08-15 10:16:13 +02:00
Nikita Malyavin
30756775d5 MDEV-29069 follow-up: support partially usable keys 2023-08-15 10:16:13 +02:00
Nikita Malyavin
bac728a263 MDEV-29069 follow-up: allow deterministic DEFAULTs 2023-08-15 10:16:13 +02:00
Nikita Malyavin
2be4c836e5 MDEV-29069 ER_KEY_NOT_FOUND on online autoinc addition + concurrent DELETE
We can't rely on keys formed with columns that were added during this
ALTER. These columns can be set with non-deterministic values, which can
end up with broken or incorrect search.

The same applies to the keys that contain reliable columns, but also have
bogus ones. Using them can narrow the search, but they're also ignored.

Also, added columns shouldn't be considered during the record match. To
determine them, table->has_value_set bitmap is used.

To fill has_value_set bitmap in the find_key call, extra unpack_row call
has been added.

For replication case, extra replica columns can be considered for this
case. We try to ignore them, too.
2023-08-15 10:16:13 +02:00
Sergei Golubchik
d1e09972f0 cleanup: cache the result of Rows_log_event::find_key() 2023-08-15 10:16:13 +02:00
Sergei Golubchik
6ecc90ae36 set table->pos_in_table_list in online alter 2023-08-15 10:16:13 +02:00
Sergei Golubchik
e72ed758c7 cleanup: remove rpl_group_info::get_table_data()
use table->pos_in_table_list instead.

Also, table->in_use is always set
2023-08-15 10:16:13 +02:00