Commit graph

402 commits

Author SHA1 Message Date
Marko Mäkelä
7830fb7f45 Merge 10.2 into 10.3 2018-08-28 12:22:56 +03:00
Marko Mäkelä
9258097fa3 Merge 10.1 into 10.2 2018-08-21 15:20:34 +03:00
Marko Mäkelä
1eb2d8f6e8 Merge 10.2 into 10.3 2018-08-16 08:54:58 +03:00
Marko Mäkelä
fa2a74e08d MDEV-16136: Prevent wrong reuse in trx_reference()
If trx_free() and trx_create_low() were called while a call to
trx_reference() was pending, we could get a reference to a wrong
transaction object.

trx_reference(): Return NULL if the trx->id no longer matches.

lock_trx_release_locks(): Assign trx->id = 0, so that trx_reference()
will not return a reference to this object.

trx_cleanup_at_db_startup(): Assign trx->id = 0.

assert_trx_is_free(): Assert !trx->n_ref. Assert trx->id == 0,
now that it will be cleared as part of a transaction commit.
2018-08-16 05:54:11 +03:00
Marko Mäkelä
6583506570 Rename lock_pool_t to lock_list
Also, replace reverse iteration with forward iteration.

lock_table_has(): Remove a redundant condition.
2018-08-16 05:53:50 +03:00
Marko Mäkelä
3ce8a0fc49 MDEV-16136: Simplify trx_lock_t memory management
Allocate trx->lock.rec_pool and trx->lock.table_pool directly from trx_t.
Remove unnecessary use of std::vector.

In order to do this, move some definitions from lock0priv.h to
lock0types.h, so that ib_lock_t will not be an opaque type.
2018-08-16 05:53:38 +03:00
Jan Lindström
3b37edee1a MDEV-13333: Deadlock failure that does not occur elsewhere
InnoDB executed code that is mean to execute only when Galera
is used and in bad luck one of the transactions is selected
incorrectly as deadlock victim. Fixed by adding wsrep_on_trx()
condition before entering actual Galera transaction handling.

No always repeatable test case for this issue is known.
2018-08-06 15:45:44 +03:00
Marko Mäkelä
05459706f2 Merge 10.2 into 10.3 2018-08-03 15:57:23 +03:00
Marko Mäkelä
be370efac4 Do not declare an unused variable 2018-08-03 14:37:31 +03:00
Marko Mäkelä
b4c377f215 Merge 10.2 into 10.3 2018-07-05 17:08:44 +03:00
Thirunarayanan Balathandayuthapani
d897b4dc25 MDEV-15855: Use atomics for dict_table_t::n_ref_count
Make dict_table_t::n_ref_count private, and protect it with
a combination of dict_sys->mutex and atomics. We want to be
able to invoke dict_table_t::release() without holding
dict_sys->mutex.
2018-07-05 15:47:51 +03:00
Marko Mäkelä
1748a31ae8 MDEV-16675 Unnecessary explicit lock acquisition during UPDATE or DELETE
In InnoDB, an INSERT will not create an explicit lock object. Instead,
the inserted record is initially implicitly locked by the transaction
that wrote its trx_t::id to the hidden system column DB_TRX_ID.
(Other transactions would check if DB_TRX_ID is referring to a
transaction that has not been committed.)

If a record was inserted in the current transaction, it would be
implicitly locked by that transaction. Only if some other transaction
is requesting access to the record, the implicit lock should be
converted to an explicit one, so that the waits-for graph can be
constructed for detecting deadlocks and lock wait timeouts.

Before this fix, InnoDB would convert implicit locks to
explicit ones, even if no conflict exists.

lock_rec_convert_impl_to_expl(): Return whether caller_trx
already holds an explicit lock that covers the record.

row_vers_impl_x_locked_low(): Avoid a lookup if the record matches
caller_trx->id.

lock_trx_has_expl_x_lock(): Renamed from lock_trx_has_rec_x_lock().

row_upd_clust_step(): In a debug assertion, check for implicit lock
before invoking lock_trx_has_expl_x_lock().

rw_trx_hash_t::find(): Make do_ref_count a mandatory parameter.
Assert that trx_id is not 0 (the caller should check it).

trx_sys_t::is_registered(): Only invoke find() if id != 0.

trx_sys_t::find(): Add the optional parameter do_ref_count.

lock_rec_queue_validate(): Avoid lookup for trx_id == 0.
2018-07-03 15:10:06 +03:00
Sergei Golubchik
36e59752e7 Merge branch '10.2' into 10.3 2018-06-30 16:39:20 +02:00
Thirunarayanan Balathandayuthapani
eb77f8cf8d MDEV-16087 Inconsistent SELECT results when query cache is enabled
The following conditions will decide the query cache retrieval or
storing inside innodb:

    (1) There should not be any locks on the table.
    (2) Some other trx shouldn't invalidated the cache before the
    transaction started.
    (3) Read view shouldn't exist. If exists then the view
    low_limit_id should be greater than or equal to the transaction that
    invalidates the cache for the particular table.

 For read-only transaction: should satisfy  the above (1) and (3)
 For read-write transaction: should satisfy the above (1), (2), (3).

 - Changed the variable from query_cache_inv_id to query_cache_inv_trx_id.

 - Moved the function row_search_check_if_query_cache_permitted from
    row0sel.h and made it as static function in ha_innodb.cc
2018-06-18 14:26:37 +05:30
Marko Mäkelä
cd15e764a8 MDEV-16159 Use atomic memory access for purge_sys
Thanks to Sergey Vojtovich for feedback and many ideas.

purge_state_t: Remove. The states are replaced with
purge_sys_t::enabled() and purge_sys_t::paused() as follows:
PURGE_STATE_INIT, PURGE_STATE_EXIT, PURGE_STATE_DISABLED: !enabled().
PURGE_STATE_RUN, PURGE_STATE_STOP: paused() distinguishes these.

purge_sys_t::m_paused: Renamed from purge_sys_t::n_stop.
Protected by atomic memory access only, not purge_sys_t::latch.

purge_sys_t::m_enabled: An atomically updated Boolean that
replaces purge_sys_t::state.

purge_sys_t:🏃 Remove, because it duplicates
srv_sys.n_threads_active[SRV_PURGE].

purge_sys_t::running(): Accessor for srv_sys.n_threads_active[SRV_PURGE].

purge_sys_t::stop(): Renamed from trx_purge_stop().

purge_sys_t::resume(): Renamed from trx_purge_run().
Do not acquire latch; solely rely on atomics.

purge_sys_t::is_initialised(), purge_sys_t::m_initialised: Remove.

purge_sys_t::create(), purge_sys_t::close(): Instead of invoking
is_initialised(), check whether event is NULL.

purge_sys_t::event: Move before latch, so that fields that are
protected by latch can reside on the same cache line with latch.

srv_start_wait_for_purge_to_start(): Merge to the only caller srv_start().
2018-05-15 23:01:18 +03:00
Marko Mäkelä
ba43914ec4 Replace dict_table_is_temporary(table) with table->is_temporary() 2018-05-12 22:12:12 +03:00
Marko Mäkelä
39d248fa55 MDEV-16092 Crash in encryption.create_or_replace
If the tablespace is dropped or truncated after the
space->is_stopping() check in fil_crypt_get_page_throttle_func(),
we would proceed to request the page, and eventually report a fatal
error.

buf_page_get_gen(): Do not retry reading if mode==BUF_GET_POSSIBLY_FREED.

lock_rec_block_validate(): Be prepared for a NULL return value when
invoking buf_page_get_gen() with mode=BUF_GET_POSSIBLY_FREED.
2018-05-04 22:44:33 +03:00
Marko Mäkelä
2b27ac8282 Fix many -Wunused-parameter
Remove unused InnoDB function parameters and functions.

i_s_sys_virtual_fill_table(): Do not allocate heap memory.

mtr_is_block_fix(): Replace with mtr_memo_contains().

mtr_is_page_fix(): Replace with mtr_memo_contains_page().
2018-05-01 16:52:19 +03:00
Marko Mäkelä
715e4f4320 MDEV-12218 Clean up InnoDB parameter validation
Bind more InnoDB parameters directly to MYSQL_SYSVAR and
remove "shadow variables".

innodb_change_buffering: Declare as ENUM, not STRING.

innodb_flush_method: Declare as ENUM, not STRING.

innodb_log_buffer_size: Bind directly to srv_log_buffer_size,
without rounding it to a multiple of innodb_page_size.

LOG_BUFFER_SIZE: Remove.

SysTablespace::normalize_size(): Renamed from normalize().

innodb_init_params(): A new function to initialize and validate
InnoDB startup parameters.

innodb_init(): Renamed from innobase_init(). Invoke innodb_init_params()
before actually trying to start up InnoDB.

srv_start(bool): Renamed from innobase_start_or_create_for_mysql().
Added the input parameter create_new_db.

SRV_ALL_O_DIRECT_FSYNC: Define only for _WIN32.

xb_normalize_init_values(): Merge to innodb_init_param().
2018-04-29 09:41:42 +03:00
Marko Mäkelä
ba19764209 Fix most -Wsign-conversion in InnoDB
Change innodb_buffer_pool_size, innodb_fill_factor to unsigned.
2018-04-28 20:45:45 +03:00
Marko Mäkelä
de942c9f61 MDEV-15983 Reduce fil_system.mutex contention further
fil_space_t::n_pending_ops, n_pending_ios: Use a combination of
fil_system.mutex and atomic memory access for protection.

fil_space_t::release(): Replaces fil_space_release().
Does not acquire fil_system.mutex.

fil_space_t::release_for_io(): Replaces fil_space_release_for_io().
Does not acquire fil_system.mutex.
2018-04-23 13:15:54 +03:00
Eugene Kosov
1513630d30 remove dead code 2018-04-09 17:21:21 +03:00
Sergey Vojtovich
0993d6b81b MDEV-15773 - trx_sys.mysql_trx_list -> trx_sys.trx_list
Replaced "list of transactions created for MySQL" with "list of all
transactions". This simplifies code and allows further removal of
trx_sys.m_views.
2018-04-04 14:09:37 +04:00
Sergey Vojtovich
061c767cce MDEV-15773 - Simplified away trx_t::in_mysql_trx_list 2018-04-04 14:09:37 +04:00
Marko Mäkelä
87ee85634c Fix a WITH_WSREP=OFF warning 2018-03-29 22:07:17 +03:00
Marko Mäkelä
428e02895b MDEV-12266: Remove dict_index_t::table_name
Replace index->table_name with index->table->name.
2018-03-29 20:47:37 +03:00
Marko Mäkelä
604fea1ad6 MDEV-12266: Remove dict_index_t::space
We can rely on the dict_table_t::space. All indexes of a table object
are always in the same tablespace. (For fulltext indexes, the data is
located in auxiliary tables, and these will continue to have their own
table objects, separate from the main table.)
2018-03-29 20:47:37 +03:00
Sergey Vojtovich
4faf34ad63 Clean-up trx_sys.mutex misuse
Currently trx_sys.mutex protects only trx_sys.mysql_trx_list and
trx_sys.m_views, which are not accessed by lock0lock debug routines.
Thus there's no need to bother trx_sys.mutex here.

Removed trx_assert_started(): this assertion is fully covered by
check_trx_state().
2018-03-29 12:24:42 +04:00
Marko Mäkelä
b81a403e69 lock_rec_enqueue_waiting(): Fix diagnostics
This is fixup after commit 8026cd6202.
We must not silently allow a lock wait to occur during InnoDB data
dictionary transactions. The dict_operation_lock is supposed to
prevent lock waits, and we want to be aware of any errors.
2018-03-28 17:32:26 +02:00
Marko Mäkelä
1924594b80 Minor (mainly non-functional) cleanup 2018-03-28 17:32:21 +02:00
Sergei Golubchik
b1818dccf7 Merge branch '10.2' into 10.3 2018-03-28 17:31:57 +02:00
Marko Mäkelä
27c54b77c1 Make some locking primitives inline
lock_rec_trx_wait(): Merge to the only caller lock_prdt_rec_move().

lock_rec_reset_nth_bit(), lock_set_lock_and_trx_wait(),
lock_reset_lock_and_trx_wait(): Define in lock0priv.h.
2018-03-16 15:50:05 +02:00
Marko Mäkelä
d2a15092c1 lock_table_create(), lock_rec_create(): Clean up the WSREP code
By definition, c_lock->trx->lock.wait_lock==c_lock cannot hold.
That is, the owner transaction of a lock cannot be waiting for that
particular lock. It must have been waiting for some other lock.
Remove the dead code related to that. Also, test c_lock for NULLness
only once.
2018-03-16 15:50:05 +02:00
Marko Mäkelä
61e192fa40 lock_reset_lock_and_trx_wait(): Remove diagnostics 2018-03-16 15:50:05 +02:00
Marko Mäkelä
27d4333cb9 MDEV-13935 INSERT stuck at state Unlocking tables
Refactor lock_grant(). With innodb_lock_schedule_algorithm=VATS
some callers were passing an incorrect parameter owns_trx_mutex
to lock_grant().

lock_grant_after_reset(): Refactored from lock_grant(), without
the call to lock_reset_lock_and_trx_wait().

lock_grant_have_trx_mutex(): A variant of lock_grant() where the
caller already holds the lock->trx->mutex. The normal lock_grant()
will acquire and release lock->trx->mutex.

lock_grant(): Define as a wrapper that will acquire lock->trx->mutex.
2018-03-16 15:50:04 +02:00
Marko Mäkelä
f93a219c72 MDEV-13935 INSERT stuck at state Unlocking tables
lock_rec_queue_validate(): Restore some assertions.

DeadlockChecker::select_victim(): Reduce the WSREP-related diff.
2018-03-16 15:50:04 +02:00
Marko Mäkelä
cac373f533 Add missing #ifdef WITH_WSREP
lock_table_create(): Move the WSREP parameter c_lock last,
and make it NULL by default, to avoid the need for a wrapper
function.

lock_table_enqueue_waiting(): Move the WSREP parameter c_lock last.
2018-03-16 15:50:04 +02:00
Marko Mäkelä
788b3ee86d Reduce the diff from 5.7 in DeadlockChecker::search()
This is a non-functional change.
2018-03-16 15:50:04 +02:00
Marko Mäkelä
bd7ed1b923 MDEV-13935 INSERT stuck at state Unlocking tables
Revert the dead code for MySQL 5.7 multi-master replication (GCS),
also known as
WL#6835: InnoDB: GCS Replication: Deterministic Deadlock Handling
(High Prio Transactions in InnoDB).

Also, make innodb_lock_schedule_algorithm=vats skip SPATIAL INDEX,
because the code does not seem to be compatible with them.

Add FIXME comments to some SPATIAL INDEX locking code. It looks
like Galera write-set replication might not work with SPATIAL INDEX.
2018-03-16 15:50:04 +02:00
Marko Mäkelä
e15e879fae Remove the unreachable error DB_QUE_THR_SUSPENDED 2018-03-16 15:50:03 +02:00
Marko Mäkelä
84129fb1b5 After-merge fix for commit 98eb9518db
The merge only covered 10.1 up to
commit 4d248974e0.

Actually merge the changes up to
commit 0a534348c7.

Also, remove the unused InnoDB field trx_t::abort_type.
2018-03-16 15:49:53 +02:00
Marko Mäkelä
ca40330d1d Fix a deadlock in thd_report_wait_for()
Unlike commit a54abf0175 claimed,
the caller of THD::awake() may actually hold the InnoDB lock_sys->mutex.
That commit introduced a deadlock of threads in the replication slave
when running the test rpl.rpl_parallel_optimistic_nobinlog.

lock_trx_handle_wait(): Expect the callers to acquire and release
lock_sys->mutex and trx->mutex.

innobase_kill_query(): Restore the logic for conditionally acquiring
and releasing the mutexes. THD::awake() can be called from inside
InnoDB while holding one or both mutexes, via thd_report_wait_for() and
via wsrep_innobase_kill_one_trx().
2018-03-16 08:23:56 +02:00
Marko Mäkelä
723f87e9d3 lock_table_create(), lock_rec_create(): Clean up the WSREP code
By definition, c_lock->trx->lock.wait_lock==c_lock cannot hold.
That is, the owner transaction of a lock cannot be waiting for that
particular lock. It must have been waiting for some other lock.
Remove the dead code related to that. Also, test c_lock for NULLness
only once.
2018-03-15 19:44:24 +02:00
Daniel Black
7bb661cd40 innodb: os_file_create_tmpfile always called with NULL -> simplify 2018-03-15 13:49:00 +11:00
Marko Mäkelä
93d495f365 MDEV-15418 innodb_force_recovery=5 displays bogus warnings
With MDEV-15132 in MariaDB 10.3.5, InnoDB no longer writes the
transaction identifier to the TRX_SYS page. The information is
only written to undo log headers and sometimes rollback segment
headers. Because the setting innodb_force_recovery=5 will skip
reading any of those pages, the maximum transaction identifier
will no longer be determined.

innobase_map_isolation_level(): Always report READ UNCOMMITTED
if innodb_force_recovery has been set to 5 or more, or
innodb_read_only is set. This will avoid errors reported by
lock_check_trx_id_sanity() and ReadView::check_trx_id_sanity().

lock_clust_rec_cons_read_sees(): Do not check for
innodb_read_only, now that innobase_map_isolation_level() will
guarantee that no read view will be created or used.

row_search_mvcc(): Do not check for innodb_force_recovery<5,
now that innobase_map_isolation_level() will guarantee that
no read view will be created or used.
2018-03-06 23:33:35 +02:00
Sergey Vojtovich
131d9a5d0c Allocate lock_sys statically
There is only one lock_sys. Allocate it statically in order to avoid
dereferencing a pointer whenever accessing it. Also, align some
members to their own cache line in order to avoid false sharing.

lock_sys_t::create(): The deferred constructor.

lock_sys_t::close(): The early destructor.
2018-02-23 08:18:18 +02:00
Sergey Vojtovich
988ec800ed MDEV-15155 - ReadView::is_open() assertion failure
ReadView::is_open() was supposed to be called by view owner thread
exclusively. Use ReadView::get_state() instead.
2018-02-22 12:26:18 +04:00
Marko Mäkelä
fb335b48b5 Allocate purge_sys statically
There is only one purge_sys. Allocate it statically in order to avoid
dereferencing a pointer whenever accessing it. Also, align some
members to their own cache line in order to avoid false sharing.

purge_sys_t::create(): The deferred constructor.

purge_sys_t::close(): The early destructor.

undo::Truncate::create(): The deferred constructor.
Because purge_sys.undo_trunc is constructed before the start-up
parameters are parsed, the normal constructor would copy a
wrong value of srv_purge_rseg_truncate_frequency.

TrxUndoRsegsIterator: Do not forward-declare an inline constructor,
because the static construction of purge_sys.rseg_iter would not have
access to it.
2018-02-22 09:30:41 +02:00
Marko Mäkelä
fe0e263e6d MDEV-15370 Upgrade fails when both insert_undo and update_undo exist
Before MDEV-12288 in MariaDB 10.3.1, InnoDB used to partition
the persistent transaction undo log into insert_undo and update_undo.

MDEV-12288 repurposes the update_undo as the single undo log.
In order to support an upgrade from earlier MariaDB versions,
the insert_undo is recovered in data structures, called old_insert.

An assertion failure occurred in TrxUndoRsegsIterator::set_next()
when an incomplete transaction was recovered with both insert_undo
and update_undo log. This could be easily demonstrated by starting
./mysql-test-run --manual-gdb innodb.read_only_recovery
in MariaDB 10.2, and after the first kill, start up the MariaDB 10.3
server with the same parameters.

The problem is that MariaDB 10.3 would roll back the recovered
transaction, and finally "commit" it twice (with all changes to
data rolled back), both insert_undo and update_undo with the same
commit end identifier (trx->no).

Our fix is to introduce a "commit number" that comprises two components:
(trx->no << 1 | !old_insert). In this way, the assertion in the purge
subsystem can be relaxed so that only the trx->no component must match.
2018-02-21 21:49:56 +02:00
Marko Mäkelä
28d844fd07 Rename the purge_sys_t iterators
purge_iter_t::operator<=(): Ordering comparison.
This replaces trx_purge_check_limit() with the difference that
we are not comparing undo_rseg_space. (In MariaDB, temporary
undo logs do not enter the purge subsystem at all.)

purge_sys_t::done: Remove. This was not used for anything.

purge_sys_t::tail: Renamed from purge_sys_t::iter.

purge_sys_t::head: Renamed from purge_sys_t::limit.
2018-02-21 19:16:47 +02:00