33
33
Finds out if an active transaction has inserted or modified a secondary
34
34
index record. NOTE: the kernel mutex is temporarily released in this
38
38
row_vers_impl_x_locked_off_kernel(
39
39
/*==============================*/
40
40
/* out: NULL if committed, else the active
41
41
transaction; NOTE that the kernel mutex is
42
42
temporarily released! */
43
rec_t* rec, /* in: record in a secondary index */
43
const rec_t* rec, /* in: record in a secondary index */
44
44
dict_index_t* index, /* in: the secondary index */
45
45
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
158
158
mem_heap_free(heap2); /* free version and clust_offsets */
160
160
if (prev_version) {
161
163
clust_offsets = rec_get_offsets(
162
164
prev_version, clust_index, NULL,
163
165
ULINT_UNDEFINED, &heap);
166
/* The stack of versions is locked by mtr.
167
Thus, it is safe to fetch the prefixes for
168
externally stored columns. */
164
169
row = row_build(ROW_COPY_POINTERS, clust_index,
165
prev_version, clust_offsets, heap);
166
entry = row_build_index_entry(row, index, heap);
170
prev_version, clust_offsets,
172
entry = row_build_index_entry(row, ext, index, heap);
173
/* entry may be NULL if a record was inserted
174
in place of a deleted record, and the BLOB
175
pointers of the new record were not
176
initialized yet. But in that case,
177
prev_version should be NULL. */
169
181
mutex_enter(&kernel_mutex);
254
266
/*********************************************************************
255
267
Finds out if we must preserve a delete marked earlier version of a clustered
256
268
index record, because it is >= the purge view. */
259
271
row_vers_must_preserve_del_marked(
260
272
/*==============================*/
286
298
if there is any not delete marked version of the record where the trx
287
299
id >= purge view, and the secondary index entry and ientry are identified in
288
300
the alphabetical ordering; exactly in this case we return TRUE. */
291
303
row_vers_old_has_index_entry(
292
304
/*=========================*/
294
306
ibool also_curr,/* in: TRUE if also rec is included in the
295
307
versions to search; otherwise only versions
296
308
prior to it are searched */
297
rec_t* rec, /* in: record in the clustered index; the
309
const rec_t* rec, /* in: record in the clustered index; the
298
310
caller must have a latch on the page */
299
311
mtr_t* mtr, /* in: mtr holding the latch on rec; it will
300
312
also hold the latch on purge_view */
301
313
dict_index_t* index, /* in: the secondary index */
302
dtuple_t* ientry) /* in: the secondary index entry */
314
const dtuple_t* ientry) /* in: the secondary index entry */
316
const rec_t* version;
305
317
rec_t* prev_version;
306
318
dict_index_t* clust_index;
307
319
ulint* clust_offsets;
308
320
mem_heap_t* heap;
309
321
mem_heap_t* heap2;
323
const dtuple_t* entry;
315
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
316
|| mtr_memo_contains(mtr, buf_block_align(rec),
317
MTR_MEMO_PAGE_S_FIX));
327
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
328
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
318
329
#ifdef UNIV_SYNC_DEBUG
319
330
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
320
331
#endif /* UNIV_SYNC_DEBUG */
329
340
ULINT_UNDEFINED, &heap);
331
342
if (also_curr && !rec_get_deleted_flag(rec, comp)) {
345
/* The stack of versions is locked by mtr.
346
Thus, it is safe to fetch the prefixes for
347
externally stored columns. */
332
348
row = row_build(ROW_COPY_POINTERS, clust_index,
333
rec, clust_offsets, heap);
334
entry = row_build_index_entry(row, index, heap);
349
rec, clust_offsets, NULL, &ext, heap);
350
entry = row_build_index_entry(row, ext, index, heap);
352
/* If entry == NULL, the record contains unset BLOB
353
pointers. This must be a freshly inserted record. If
355
row_purge_remove_sec_if_poss_low(), the thread will
356
hold latches on the clustered index and the secondary
357
index. Because the insert works in three steps:
359
(1) insert the record to clustered index
360
(2) store the BLOBs and update BLOB pointers
361
(3) insert records to secondary indexes
363
the purge thread can safely ignore freshly inserted
364
records and delete the secondary index record. The
365
thread that inserted the new record will be inserting
366
the secondary index records. */
336
368
/* NOTE that we cannot do the comparison as binary
337
369
fields because the row is maybe being modified so that
338
the clustered index record has already been updated
339
to a different binary value in a char field, but the
370
the clustered index record has already been updated to
371
a different binary value in a char field, but the
340
372
collation identifies the old and new value anyway! */
342
if (dtuple_datas_are_ordering_equal(ientry, entry)) {
373
if (entry && !dtuple_coll_cmp(ientry, entry)) {
344
375
mem_heap_free(heap);
369
400
NULL, ULINT_UNDEFINED, &heap);
371
402
if (!rec_get_deleted_flag(prev_version, comp)) {
405
/* The stack of versions is locked by mtr.
406
Thus, it is safe to fetch the prefixes for
407
externally stored columns. */
372
408
row = row_build(ROW_COPY_POINTERS, clust_index,
373
prev_version, clust_offsets, heap);
374
entry = row_build_index_entry(row, index, heap);
409
prev_version, clust_offsets,
411
entry = row_build_index_entry(row, ext, index, heap);
413
/* If entry == NULL, the record contains unset
414
BLOB pointers. This must be a freshly
415
inserted record that we can safely ignore.
416
For the justification, see the comments after
417
the previous row_build_index_entry() call. */
376
419
/* NOTE that we cannot do the comparison as binary
377
420
fields because maybe the secondary index record has
395
438
Constructs the version of a clustered index record which a consistent
396
439
read should see. We assume that the trx id stored in rec is such that
397
440
the consistent read should not see rec in its present version. */
400
443
row_vers_build_for_consistent_read(
401
444
/*===============================*/
402
445
/* out: DB_SUCCESS or DB_MISSING_HISTORY */
403
rec_t* rec, /* in: record in a clustered index; the
446
const rec_t* rec, /* in: record in a clustered index; the
404
447
caller must have a latch on the page; this
405
448
latch locks the top of the stack of versions
406
449
of this records */
412
455
mem_heap_t** offset_heap,/* in/out: memory heap from which
413
456
the offsets are allocated */
414
457
mem_heap_t* in_heap,/* in: memory heap from which the memory for
415
old_vers is allocated; memory for possible
458
*old_vers is allocated; memory for possible
416
459
intermediate versions is allocated and freed
417
460
locally within the function */
418
461
rec_t** old_vers)/* out, own: old version, or NULL if the
419
462
record does not exist in the view, that is,
420
463
it was freshly inserted afterwards */
465
const rec_t* version;
423
466
rec_t* prev_version;
425
468
mem_heap_t* heap = NULL;
429
ut_ad(index->type & DICT_CLUSTERED);
430
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
431
|| mtr_memo_contains(mtr, buf_block_align(rec),
432
MTR_MEMO_PAGE_S_FIX));
472
ut_ad(dict_index_is_clust(index));
473
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
474
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
433
475
#ifdef UNIV_SYNC_DEBUG
434
476
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
435
477
#endif /* UNIV_SYNC_DEBUG */
528
570
/*********************************************************************
529
571
Constructs the last committed version of a clustered index record,
530
572
which should be seen by a semi-consistent read. */
533
575
row_vers_build_for_semi_consistent_read(
534
576
/*====================================*/
535
577
/* out: DB_SUCCESS or DB_MISSING_HISTORY */
536
rec_t* rec, /* in: record in a clustered index; the
578
const rec_t* rec, /* in: record in a clustered index; the
537
579
caller must have a latch on the page; this
538
580
latch locks the top of the stack of versions
539
581
of this records */
544
586
mem_heap_t** offset_heap,/* in/out: memory heap from which
545
587
the offsets are allocated */
546
588
mem_heap_t* in_heap,/* in: memory heap from which the memory for
547
old_vers is allocated; memory for possible
589
*old_vers is allocated; memory for possible
548
590
intermediate versions is allocated and freed
549
591
locally within the function */
550
rec_t** old_vers)/* out, own: rec, old version, or NULL if the
592
const rec_t** old_vers)/* out: rec, old version, or NULL if the
551
593
record does not exist in the view, that is,
552
594
it was freshly inserted afterwards */
596
const rec_t* version;
555
597
mem_heap_t* heap = NULL;
558
dulint rec_trx_id = ut_dulint_create(0, 0);
600
dulint rec_trx_id = ut_dulint_zero;
560
ut_ad(index->type & DICT_CLUSTERED);
561
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
562
|| mtr_memo_contains(mtr, buf_block_align(rec),
563
MTR_MEMO_PAGE_S_FIX));
602
ut_ad(dict_index_is_clust(index));
603
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
604
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
564
605
#ifdef UNIV_SYNC_DEBUG
565
606
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
566
607
#endif /* UNIV_SYNC_DEBUG */