@@ -168,49 +168,71 @@ trx_rseg_mem_create(ulint id, ulint space, ulint page_no)
168168return (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 */
174176static
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_t node_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) ) {
200215my_atomic_addlint (&trx_sys.rseg_history_len , len);
201216
202- node_addr = trx_purge_get_log_from_hist (
217+ fil_addr_t node_addr = trx_purge_get_log_from_hist (
203218flst_get_last (rseg_header + TRX_RSEG_HISTORY, mtr));
204219
205220rseg->last_page_no = node_addr.page ;
206221rseg->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 (
209224page_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+ }
214236unsigned purge = mach_read_from_2 (
215237undo_log_hdr + TRX_UNDO_NEEDS_PURGE);
216238ut_ad (purge <= 1 );
@@ -233,11 +255,30 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
233255void
234256trx_rseg_array_init ()
235257{
236- mtr_t mtr ;
258+ trx_id_t max_trx_id = 0 ;
237259
238260for (ulint rseg_id = 0 ; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
261+ mtr_t mtr;
239262mtr.start ();
240263if (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+ }
241282const uint32_t page_no = trx_sysf_rseg_get_page_no (
242283sys, rseg_id);
243284if (page_no != FIL_NULL) {
@@ -249,12 +290,14 @@ trx_rseg_array_init()
249290ut_ad (rseg->id == rseg_id);
250291ut_ad (!trx_sys.rseg_array [rseg_id]);
251292trx_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
256297mtr.commit ();
257298}
299+
300+ trx_sys.init_max_trx_id (max_trx_id);
258301}
259302
260303/* * Create a persistent rollback segment.
0 commit comments