Skip to content

Commit a4d2cc9

Browse files
committed
MDEV-35174 Possible hang in trx_undo_prev_version()
In commit b7b9f3c (MDEV-34515) we accidentally made the InnoDB MVCC code acquire a shared purge_sys.latch twice. Recursive shared latch acquisition may cause a deadlock of InnoDB threads if another thread in between will start waiting for an exclusive latch. purge_sys_t::latch: In debug builds, use srw_lock_debug instead of srw_spin_lock, so that bugs like this will result in debug assertion failures. trx_undo_report_row_operation(): Pass the view_guard to trx_undo_prev_version() and the rest of the arguments in the same order, so that the work to permute argument registers is minimized.
1 parent 9849e3f commit a4d2cc9

File tree

2 files changed

+13
-7
lines changed

2 files changed

+13
-7
lines changed

storage/innobase/include/trx0purge.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ class purge_sys_t
125125

126126
public:
127127
/** latch protecting view, m_enabled */
128-
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mutable srw_spin_lock latch;
128+
alignas(CPU_LEVEL1_DCACHE_LINESIZE)
129+
mutable IF_DBUG(srw_lock_debug,srw_spin_lock) latch;
129130
private:
130131
/** Read view at the start of a purge batch. Any encountered index records
131132
that are older than view will be removed. */

storage/innobase/trx/trx0rec.cc

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,8 +2040,10 @@ trx_undo_report_row_operation(
20402040

20412041
static dberr_t trx_undo_prev_version(const rec_t *rec, dict_index_t *index,
20422042
rec_offs *offsets, mem_heap_t *heap,
2043-
rec_t **old_vers, mem_heap_t *v_heap,
2044-
dtuple_t **vrow, ulint v_status,
2043+
rec_t **old_vers,
2044+
const purge_sys_t::view_guard &check,
2045+
ulint v_status,
2046+
mem_heap_t *v_heap, dtuple_t **vrow,
20452047
const trx_undo_rec_t *undo_rec);
20462048

20472049
inline const buf_block_t *
@@ -2142,7 +2144,8 @@ dberr_t trx_undo_prev_version_build(const rec_t *rec, dict_index_t *index,
21422144
if (UNIV_UNLIKELY(end > offset &&
21432145
end < srv_page_size - FIL_PAGE_DATA_END))
21442146
err= trx_undo_prev_version(rec, index, offsets, heap,
2145-
old_vers, v_heap, vrow, v_status, undo_rec);
2147+
old_vers, check, v_status, v_heap, vrow,
2148+
undo_rec);
21462149
}
21472150
}
21482151

@@ -2152,8 +2155,10 @@ dberr_t trx_undo_prev_version_build(const rec_t *rec, dict_index_t *index,
21522155

21532156
static dberr_t trx_undo_prev_version(const rec_t *rec, dict_index_t *index,
21542157
rec_offs *offsets, mem_heap_t *heap,
2155-
rec_t **old_vers, mem_heap_t *v_heap,
2156-
dtuple_t **vrow, ulint v_status,
2158+
rec_t **old_vers,
2159+
const purge_sys_t::view_guard &check,
2160+
ulint v_status,
2161+
mem_heap_t *v_heap, dtuple_t **vrow,
21572162
const trx_undo_rec_t *undo_rec)
21582163
{
21592164
byte type, cmpl_info;
@@ -2223,7 +2228,7 @@ static dberr_t trx_undo_prev_version(const rec_t *rec, dict_index_t *index,
22232228
the BLOB. */
22242229

22252230
if (update->info_bits & REC_INFO_DELETED_FLAG
2226-
&& purge_sys.is_purgeable(trx_id)) {
2231+
&& check.view().changes_visible(trx_id)) {
22272232
return DB_SUCCESS;
22282233
}
22292234

0 commit comments

Comments
 (0)