Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-23244

ALTER TABLE…ADD PRIMARY KEY fails to flag duplicate key error from concurrent DML

    XMLWordPrintable

    Details

      Description

      This failure had been reported in MDEV-15533, which was filed about a different failure in 10.2.

      There are multiple assertions log->blobs in the function row_log_table_apply_update(). The one that fails in the rr replay trace appears to be specific to 10.3 and later, likely caused by MDEV-12288:

      		if (memcmp(rec_trx_id, old_pk_trx_id->data,
      			   DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)) {
      			/* The ROW_T_UPDATE was logged for a different
      			DB_TRX_ID,DB_ROLL_PTR. This is possible if an
      			earlier ROW_T_INSERT or ROW_T_UPDATE was diverted
      			because some BLOBs were missing due to rolling
      			back the initial insert or due to purging
      			the old BLOB values of an update. */
      			ut_ad(log->blobs);
      

      In the trace that I analyzed, old_trx_id->data is reset_trx_id.

      The value was assigned earlier:

      #0  0x000055bd086d1405 in dfield_set_data (len=6, 
          data=0x55bd0997f4e0 <reset_trx_id>, field=0x61200036ddb0)
          at /home/mleich/10.5_A/storage/innobase/include/data0data.ic:93
      #1  row_log_table_get_pk (rec=<optimized out>, 
          index=index@entry=0x61800020f520, offsets=offsets@entry=0x7f9a4025f9d0, 
          sys=sys@entry=0x0, heap=heap@entry=0x7f9a4025f6f0)
          at /home/mleich/10.5_A/storage/innobase/row/row0log.cc:1416
      #2  0x000055bd0876a3fd in row_upd_clust_rec (flags=flags@entry=0, 
          node=node@entry=0x621000c6f220, index=index@entry=0x61800020f520, 
          offsets=<optimized out>, offsets@entry=0x7f9a4025f9d0, 
          offsets_heap=offsets_heap@entry=0x7f9a4025f850, 
          thr=thr@entry=0x621000c6f600, mtr=<optimized out>)
          at /home/mleich/10.5_A/storage/innobase/row/row0upd.cc:2550
      

      The code in row_log_table_get_pk() is directly related to this:

      		if (trx_read_trx_id(trx_roll) < log->min_trx) {
      			trx_roll = reset_trx_id;
      			if (sys) {
      				memcpy(sys, trx_roll,
      				       DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
      			}
      ...
      		}
       
      		ut_d(trx_id_check(trx_roll, log->min_trx));
       
      		dfield_set_data(dtuple_get_nth_field(tuple, new_n_uniq),
      				trx_roll, DATA_TRX_ID_LEN);
      		dfield_set_data(dtuple_get_nth_field(tuple, new_n_uniq + 1),
      				trx_roll + DATA_TRX_ID_LEN, DATA_ROLL_PTR_LEN);
      

      We should adjust the condition to take log->min_trx into account. At the time of the mismatch, we have mach_read_from_6(rec_trx_id) == 6388 and log->min_trx == 6385. It seems that we are correctly treating this as a mismatch of the DB_TRX_ID, because in row_log_table_get_pk() the original DB_TRX_ID must have been smaller than 6385. So, this might be a 'harmless' debug assertion failure.

      This should only affect cases where the PRIMARY KEY is being redefined while concurrent DML is being executed. In the trace that I analyzed, ALTER TABLE t2 ADD PRIMARY KEY (col2) was being executed.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              marko Marko Mäkelä
              Reporter:
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: