Skip to content

Commit 6058f92

Browse files
committed
Simplify undo log access during InnoDB startup
trx_rseg_mem_restore(): Update the max_trx_id from the undo log pages. trx_sys_init_at_db_start(): Remove; merge with trx_lists_init_at_db_start(). trx_undo_lists_init(): Move to the only calling module, trx0rseg.cc. trx_undo_mem_create_at_db_start(): Declare globally. Return the number of pages.
1 parent d24229b commit 6058f92

File tree

7 files changed

+119
-181
lines changed

7 files changed

+119
-181
lines changed

storage/innobase/include/trx0sys.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ trx_sys_hdr_page(const page_id_t& page_id)
5858
&& page_id.page_no() == TRX_SYS_PAGE_NO);
5959
}
6060

61-
/** Initialize the transaction system main-memory data structures. */
62-
void trx_sys_init_at_db_start();
63-
6461
/*****************************************************************//**
6562
Creates and initializes the transaction system at the database creation. */
6663
void

storage/innobase/include/trx0undo.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,6 @@ trx_undo_truncate_start(
210210
ulint hdr_page_no,
211211
ulint hdr_offset,
212212
undo_no_tlimit);
213-
/********************************************************************//**
214-
Initializes the undo log lists for a rollback segment memory copy.
215-
This function is only called when the database is started or a new
216-
rollback segment created.
217-
@return the combined size of undo log segments in pages */
218-
ulint
219-
trx_undo_lists_init(
220-
/*================*/
221-
trx_rseg_t* rseg);/*!< in: rollback segment memory object */
222213
/** Assign an undo log for a persistent transaction.
223214
A new undo log is created or a cached undo log reused.
224215
@param[in,out] trx transaction
@@ -326,6 +317,13 @@ trx_undo_parse_page_header(
326317
const byte* end_ptr,
327318
page_t* page,
328319
mtr_t* mtr);
320+
/** Read an undo log when starting up the database.
321+
@param[in,out] rseg rollback segment
322+
@param[in] id rollback segment slot
323+
@param[in] page_no undo log segment page number
324+
@return size of the undo log in pages */
325+
ulint
326+
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no);
329327
/************************************************************************
330328
Frees an undo log memory copy. */
331329
void

storage/innobase/srv/srv0start.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,7 +2173,7 @@ innobase_start_or_create_for_mysql()
21732173
All the remaining rollback segments will be created later,
21742174
after the double write buffer has been created. */
21752175
trx_sys_create_sys_pages();
2176-
trx_sys_init_at_db_start();
2176+
trx_lists_init_at_db_start();
21772177

21782178
err = dict_create();
21792179

@@ -2234,7 +2234,7 @@ innobase_start_or_create_for_mysql()
22342234
}
22352235
/* This must precede
22362236
recv_apply_hashed_log_recs(true). */
2237-
trx_sys_init_at_db_start();
2237+
trx_lists_init_at_db_start();
22382238
break;
22392239
case SRV_OPERATION_RESTORE_DELTA:
22402240
case SRV_OPERATION_BACKUP:
@@ -2325,7 +2325,7 @@ innobase_start_or_create_for_mysql()
23252325
}
23262326

23272327
/* recv_recovery_from_checkpoint_finish needs trx lists which
2328-
are initialized in trx_sys_init_at_db_start(). */
2328+
are initialized in trx_lists_init_at_db_start(). */
23292329

23302330
recv_recovery_from_checkpoint_finish();
23312331

storage/innobase/trx/trx0rseg.cc

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -168,49 +168,71 @@ trx_rseg_mem_create(ulint id, ulint space, ulint page_no)
168168
return(rseg);
169169
}
170170

171-
/** Restore the state of a persistent rollback segment.
172-
@param[in,out] rseg persistent rollback segment
173-
@param[in,out] mtr mini-transaction */
171+
/** Read the undo log lists.
172+
@param[in,out] rseg rollback segment
173+
@param[in] rseg_header rollback segment header
174+
@param[in,out] mtr mini-transaction
175+
@return the combined size of undo log segments in pages */
174176
static
175-
void
176-
trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
177+
ulint
178+
trx_undo_lists_init(trx_rseg_t* rseg, const trx_rsegf_t* rseg_header,
179+
mtr_t* mtr)
177180
{
178-
ulint len;
179-
fil_addr_tnode_addr;
180-
trx_rsegf_t* rseg_header;
181-
trx_ulogf_t* undo_log_hdr;
182-
ulint sum_of_undo_sizes;
181+
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
183182

184-
rseg_header = trx_rsegf_get_new(rseg->space, rseg->page_no, mtr);
183+
ulint size = 0;
185184

186-
rseg->max_size = mtr_read_ulint(
187-
rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, mtr);
185+
for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) {
186+
ulint page_no = trx_rsegf_get_nth_undo(rseg_header, i);
187+
if (page_no != FIL_NULL) {
188+
size += trx_undo_mem_create_at_db_start(
189+
rseg, i, page_no);
190+
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
191+
}
192+
}
188193

189-
/* Initialize the undo log lists according to the rseg header */
194+
return(size);
195+
}
190196

191-
sum_of_undo_sizes = trx_undo_lists_init(rseg);
197+
/** Restore the state of a persistent rollback segment.
198+
@param[in,out] rseg persistent rollback segment
199+
@param[in,out] max_trx_id maximum observed transaction identifier
200+
@param[in,out] mtr mini-transaction */
201+
static
202+
void
203+
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
204+
{
205+
const trx_rsegf_t* rseg_header = trx_rsegf_get_new(
206+
rseg->space, rseg->page_no, mtr);
207+
rseg->max_size = mach_read_from_4(rseg_header + TRX_RSEG_MAX_SIZE);
192208

193-
rseg->curr_size = mtr_read_ulint(
194-
rseg_header + TRX_RSEG_HISTORY_SIZE, MLOG_4BYTES, mtr)
195-
+ 1 + sum_of_undo_sizes;
209+
/* Initialize the undo log lists according to the rseg header */
196210

197-
len = flst_get_len(rseg_header + TRX_RSEG_HISTORY);
211+
rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE)
212+
+ 1 + trx_undo_lists_init(rseg, rseg_header, mtr);
198213

199-
if (len > 0) {
214+
if (ulint len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) {
200215
my_atomic_addlint(&trx_sys.rseg_history_len, len);
201216

202-
node_addr = trx_purge_get_log_from_hist(
217+
fil_addr_tnode_addr = trx_purge_get_log_from_hist(
203218
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
204219

205220
rseg->last_page_no = node_addr.page;
206221
rseg->last_offset = node_addr.boffset;
207222

208-
undo_log_hdr = trx_undo_page_get(
223+
const trx_ulogf_t*undo_log_hdr = trx_undo_page_get(
209224
page_id_t(rseg->space, node_addr.page), mtr)
210225
+ node_addr.boffset;
211226

212-
rseg->last_trx_no = mach_read_from_8(
213-
undo_log_hdr + TRX_UNDO_TRX_NO);
227+
trx_id_t id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_ID);
228+
if (id > max_trx_id) {
229+
max_trx_id = id;
230+
}
231+
id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_NO);
232+
rseg->last_trx_no = id;
233+
if (id > max_trx_id) {
234+
max_trx_id = id;
235+
}
214236
unsigned purge = mach_read_from_2(
215237
undo_log_hdr + TRX_UNDO_NEEDS_PURGE);
216238
ut_ad(purge <= 1);
@@ -233,11 +255,30 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
233255
void
234256
trx_rseg_array_init()
235257
{
236-
mtr_tmtr;
258+
trx_id_t max_trx_id = 0;
237259

238260
for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
261+
mtr_t mtr;
239262
mtr.start();
240263
if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) {
264+
if (rseg_id == 0) {
265+
/* VERY important: after the database
266+
is started, max_trx_id value is
267+
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN,
268+
and the first call of
269+
trx_sys.get_new_trx_id() will invoke
270+
flush_max_trx_id()! Thus trx id values
271+
will not overlap when the database is
272+
repeatedly started! */
273+
274+
max_trx_id = 2 * TRX_SYS_TRX_ID_WRITE_MARGIN
275+
+ ut_uint64_align_up(
276+
mach_read_from_8(
277+
TRX_SYS
278+
+ TRX_SYS_TRX_ID_STORE
279+
+ sys->frame),
280+
TRX_SYS_TRX_ID_WRITE_MARGIN);
281+
}
241282
const uint32_tpage_no = trx_sysf_rseg_get_page_no(
242283
sys, rseg_id);
243284
if (page_no != FIL_NULL) {
@@ -249,12 +290,14 @@ trx_rseg_array_init()
249290
ut_ad(rseg->id == rseg_id);
250291
ut_ad(!trx_sys.rseg_array[rseg_id]);
251292
trx_sys.rseg_array[rseg_id] = rseg;
252-
trx_rseg_mem_restore(rseg, &mtr);
293+
trx_rseg_mem_restore(rseg, max_trx_id, &mtr);
253294
}
254295
}
255296

256297
mtr.commit();
257298
}
299+
300+
trx_sys.init_max_trx_id(max_trx_id);
258301
}
259302

260303
/** Create a persistent rollback segment.

storage/innobase/trx/trx0sys.cc

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -415,39 +415,6 @@ trx_sysf_create(
415415
ut_a(page_no == FSP_FIRST_RSEG_PAGE_NO);
416416
}
417417

418-
/** Initialize the transaction system main-memory data structures. */
419-
void
420-
trx_sys_init_at_db_start()
421-
{
422-
/* VERY important: after the database is started, max_trx_id value is
423-
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the 'if' in
424-
trx_sys.get_new_trx_id will evaluate to TRUE when the function
425-
is first time called, and the value for trx id will be written
426-
to the disk-based header! Thus trx id values will not overlap when
427-
the database is repeatedly started! */
428-
429-
mtr_tmtr;
430-
mtr.start();
431-
432-
buf_block_t* block = trx_sysf_get(&mtr);
433-
434-
trx_id_t max_trx_id = block
435-
? 2 * TRX_SYS_TRX_ID_WRITE_MARGIN
436-
+ ut_uint64_align_up(mach_read_from_8(TRX_SYS
437-
+ TRX_SYS_TRX_ID_STORE
438-
+ block->frame),
439-
TRX_SYS_TRX_ID_WRITE_MARGIN)
440-
: 0;
441-
trx_sys.init_max_trx_id(max_trx_id);
442-
443-
mtr.commit();
444-
445-
trx_dummy_sess = sess_open();
446-
447-
trx_lists_init_at_db_start();
448-
trx_sys.mvcc.clone_oldest_view(&purge_sys->view);
449-
}
450-
451418
/** Create the instance */
452419
void
453420
trx_sys_t::create()

storage/innobase/trx/trx0trx.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -895,22 +895,23 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
895895
void
896896
trx_lists_init_at_db_start()
897897
{
898-
uint64_trows_to_undo = 0;
899898
ut_a(srv_is_being_started);
900899
ut_ad(!srv_was_started);
901900
ut_ad(!purge_sys);
902-
903-
purge_sys = UT_NEW_NOKEY(purge_sys_t());
901+
ut_ad(!trx_dummy_sess);
904902

905903
if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
906904
return;
907905
}
908906

907+
trx_dummy_sess = sess_open();
908+
purge_sys = UT_NEW_NOKEY(purge_sys_t());
909909
trx_rseg_array_init();
910910

911911
/* Look from the rollback segments if there exist undo logs for
912912
transactions. */
913-
const ib_time_t start_time = ut_time();
913+
const ib_time_tstart_time = ut_time();
914+
uint64_trows_to_undo = 0;
914915

915916
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
916917
trx_undo_t* undo;
@@ -979,6 +980,7 @@ trx_lists_init_at_db_start()
979980
}
980981

981982
std::sort(trx_sys.rw_trx_ids.begin(), trx_sys.rw_trx_ids.end());
983+
trx_sys.mvcc.clone_oldest_view(&purge_sys->view);
982984
}
983985

984986
/** Assign a persistent rollback segment in a round-robin fashion,

0 commit comments

Comments
 (0)