@@ -41,15 +41,14 @@ namespace lob {
4141/* * Rollback from undo log information.
4242@param[in] ctx the delete operation context.
4343@param[in] index the clustered index to which LOB belongs.
44- @param[in] ref the LOB reference object.
4544@param[in] uf the update vector of concerned field. */
4645static void rollback_from_undolog (DeleteContext *ctx, dict_index_t *index,
47- ref_t &ref, const upd_field_t *uf) {
46+ const upd_field_t *uf) {
4847 DBUG_TRACE;
4948
5049 trx_t *trx = nullptr ;
5150
52- dberr_t err = apply_undolog (ctx->get_mtr (), trx, index, ref , uf);
51+ dberr_t err = apply_undolog (ctx->get_mtr (), trx, index, ctx-> m_blobref , uf);
5352 ut_a (err == DB_SUCCESS);
5453}
5554
@@ -59,21 +58,21 @@ static void rollback_from_undolog(DeleteContext *ctx, dict_index_t *index,
5958@param[in] trxid the transaction that is being rolled back.
6059@param[in] undo_no during rollback to savepoint, rollback only
6160 upto this undo number.
62- @param[in] ref reference to LOB that is being rolled back.
6361@param[in] rec_type undo record type.
6462@param[in] uf update vector of the concerned field. */
6563static void rollback (DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
66- undo_no_t undo_no, ref_t &ref, ulint rec_type,
67- const upd_field_t *uf) {
64+ undo_no_t undo_no, ulint rec_type, const upd_field_t *uf) {
6865 DBUG_TRACE;
6966
67+ ref_t &ref = ctx->m_blobref ;
68+
7069 ut_ad (ctx->m_rollback );
7170
7271 if (uf != nullptr && uf->lob_diffs != nullptr && uf->lob_diffs ->size () > 0 ) {
7372 /* Undo log contains changes done to the LOB. This must have
7473 been a small change done to LOB. Apply the undo log on the
7574 LOB.*/
76- rollback_from_undolog (ctx, index, ref, uf);
75+ rollback_from_undolog (ctx, index, uf);
7776 return ;
7877 }
7978
@@ -181,12 +180,13 @@ static void rollback(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
181180@param[in] trxid the transaction that is being rolled back.
182181@param[in] undo_no during rollback to savepoint, rollback only
183182 upto this undo number.
184- @param[in] ref reference to LOB that is purged.
185183@param[in] rec_type undo record type. */
186184static void z_rollback (DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
187- undo_no_t undo_no, ref_t &ref, ulint rec_type) {
185+ undo_no_t undo_no, ulint rec_type) {
188186 ut_ad (ctx->m_rollback );
189187
188+ ref_t &ref = ctx->m_blobref ;
189+
190190 mtr_t local_mtr;
191191 mtr_start (&local_mtr);
192192
@@ -196,7 +196,7 @@ static void z_rollback(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
196196 data should not be read. OTOH we do not ref.set_page_no(FIL_NULL, 0)
197197 until we delete all the pages, so that the recovery can use the reference to
198198 find the remaining parts of the LOB. */
199- ref.set_length (0 , 0 );
199+ ref.set_length (0 , nullptr );
200200 ctx->zblob_write_blobref (ctx->m_field_no , &local_mtr);
201201
202202 page_no_t first_page_no = ref.page_no ();
@@ -256,7 +256,7 @@ static void z_rollback(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
256256 ut_ad (ctx->get_page_zip () != nullptr );
257257 /* We are done with cleaning up index entries for the given version, so now we
258258 can modify the reference, so that it is no longer reachable. */
259- ref.set_page_no (FIL_NULL, 0 );
259+ ref.set_page_no (FIL_NULL, nullptr );
260260 ut_ad (ref.length () == 0 );
261261 ctx->x_latch_rec_page (&local_mtr);
262262 ctx->zblob_write_blobref (ctx->m_field_no , &local_mtr);
@@ -272,14 +272,14 @@ static void z_rollback(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
272272@param[in] trxid the transaction that is being purged.
273273@param[in] undo_no during rollback to savepoint, purge only upto
274274 this undo number.
275- @param[in] ref reference to LOB that is purged.
276275@param[in] rec_type undo record type. */
277276static void z_purge (DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
278- undo_no_t undo_no, ref_t &ref, ulint rec_type) {
277+ undo_no_t undo_no, ulint rec_type) {
279278 const bool is_rollback = ctx->m_rollback ;
279+ ref_t &ref = ctx->m_blobref ;
280280
281281 if (is_rollback) {
282- z_rollback (ctx, index, trxid, undo_no, ref, rec_type);
282+ z_rollback (ctx, index, trxid, undo_no, rec_type);
283283 return ;
284284 }
285285
@@ -366,21 +366,12 @@ static void z_purge(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
366366 }
367367}
368368
369- /* * Purge an uncompressed LOB.
370- @param[in] ctx the delete operation context information.
371- @param[in] index clustered index in which LOB is present
372- @param[in] trxid the transaction that is being purged.
373- @param[in] undo_no during rollback to savepoint, purge only upto
374- this undo number.
375- @param[in] ref reference to LOB that is purged.
376- @param[in] rec_type undo record type.
377- @param[in] uf the update vector for the field. */
378369void purge (DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
379- undo_no_t undo_no, ref_t ref, ulint rec_type,
380- const upd_field_t *uf) {
370+ undo_no_t undo_no, ulint rec_type, const upd_field_t *uf) {
381371 DBUG_TRACE;
382372 mtr_t lob_mtr;
383373
374+ ref_t &ref = ctx->m_blobref ;
384375 mtr_t *mtr = ctx->get_mtr ();
385376 const mtr_log_t log_mode = mtr->get_log_mode ();
386377 const bool is_rollback = ctx->m_rollback ;
@@ -409,29 +400,46 @@ void purge(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
409400 return ;
410401 }
411402
412- /* Below we will restart the btr_mtr. Between the cursor store and restore,
413- it is possible that the position of the record changes and hence the lob
414- reference could become invalid. To avoid this take the latches before
415- restarting the btr_mtr. */
416-
417- mtr_start (&lob_mtr);
418- mtr_sx_lock (dict_index_get_lock (index), &lob_mtr);
419-
403+ /* The purpose of the following block is to ensure that the parent mtr does
404+ not hold any redo log while creating child mtrs. */
420405 if (ctx->m_pcur != nullptr ) {
406+ /* Below we will restart the btr_mtr. Between the cursor store and restore,
407+ it is possible that the position of the record changes and hence the lob
408+ reference could become invalid. Reset it to correct value. */
421409 ctx->restart_mtr ();
410+ byte *field_ref = ctx->get_field_ref (ctx->m_field_no );
411+ ref.set_ref (field_ref);
422412 } else {
413+ /* Since pcur is not available, take latches to ensure that the record
414+ position does not change. We imitate the purge thread for the latches
415+ taken and the order in which they are taken. Kindly refer to the
416+ function row_purge_upd_exist_or_extern_func(). */
417+ mtr_start (&lob_mtr);
418+ mtr_sx_lock (dict_index_get_lock (index), &lob_mtr);
419+ btr_root_get (index, &lob_mtr);
423420 ctx->x_latch_rec_page (&lob_mtr);
424421 ctx->restart_mtr ();
425422 mtr_sx_lock (dict_index_get_lock (index), mtr);
423+ btr_root_get (index, mtr);
426424 ctx->x_latch_rec_page (mtr);
425+ mtr_commit (&lob_mtr);
427426 }
428- mtr_commit (&lob_mtr);
429427
430- space_id_t space_id = ref.space_id ();
428+ /* If rec_type is 0, it is not the purge operation. */
429+ if (!is_rollback && rec_type != 0 && !ctx->is_delete_marked ()) {
430+ /* This is the purge operation. The delete marked clustered record has been
431+ reused. Purge shouldn't proceed. */
432+ return ;
433+ }
434+
435+ ut_ad (ctx->is_ref_valid ());
431436
437+ space_id_t space_id = ref.space_id ();
438+ ut_ad (space_id == index->space_id ());
432439 page_no_t first_page_no = ref.page_no ();
433440 page_id_t page_id (space_id, first_page_no);
434441 page_size_t page_size (dict_table_page_size (index->table ));
442+
435443 page_type_t page_type =
436444 first_page_t::get_page_type (index, page_id, page_size);
437445
@@ -445,14 +453,14 @@ void purge(DeleteContext *ctx, dict_index_t *index, trx_id_t trxid,
445453 }
446454
447455 if (page_type == FIL_PAGE_TYPE_ZLOB_FIRST) {
448- z_purge (ctx, index, trxid, undo_no, ref, rec_type);
456+ z_purge (ctx, index, trxid, undo_no, rec_type);
449457 return ;
450458 }
451459
452460 ut_a (page_type == FIL_PAGE_TYPE_LOB_FIRST);
453461
454462 if (is_rollback) {
455- rollback (ctx, index, trxid, undo_no, ref, rec_type, uf);
463+ rollback (ctx, index, trxid, undo_no, rec_type, uf);
456464 return ;
457465 }
458466
0 commit comments