1
/*****************************************************************************
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
1
19
/******************************************************
6
22
Created 7/19/1997 Heikki Tuuri
7
23
*******************************************************/
137
153
/* Buffer pool size per the maximum insert buffer size */
138
154
#define IBUF_POOL_SIZE_PER_MAX_SIZE 2
140
/* The insert buffer control structure */
156
/* Table name for the insert buffer. */
157
#define IBUF_TABLE_NAME "SYS_IBUF_TABLE"
159
/** Operations that can currently be buffered. */
160
UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_INSERT;
162
/** The insert buffer control structure */
141
163
UNIV_INTERN ibuf_t* ibuf = NULL;
143
static ulint ibuf_rnd = 986058871;
145
165
UNIV_INTERN ulint ibuf_flush_count = 0;
147
167
#ifdef UNIV_IBUF_COUNT_DEBUG
148
168
/* Dimensions for the ibuf_count array */
149
#define IBUF_COUNT_N_SPACES 500
150
#define IBUF_COUNT_N_PAGES 2000
169
#define IBUF_COUNT_N_SPACES 4
170
#define IBUF_COUNT_N_PAGES 130000
152
172
/* Buffered entry counts for file pages, used in debugging */
153
173
static ulint ibuf_counts[IBUF_COUNT_N_SPACES][IBUF_COUNT_N_PAGES];
230
250
still physically like the index page even if the index would have been
231
251
dropped! So, there seems to be no problem. */
234
/**********************************************************************
235
Validates the ibuf data structures when the caller owns ibuf_mutex. */
238
ibuf_validate_low(void);
239
/*===================*/
240
/* out: TRUE if ok */
241
#endif /* UNIV_DEBUG */
242
253
/**********************************************************************
243
254
Sets the flag in the current OS thread local storage denoting that it is
244
255
inside an insert buffer routine. */
293
304
ibuf_header_page_get(
294
305
/*=================*/
295
306
/* out: insert buffer header page */
296
ulint space, /* in: space id */
297
307
mtr_t* mtr) /* in: mtr */
299
309
buf_block_t* block;
303
311
ut_ad(!ibuf_inside());
305
block = buf_page_get(space, 0, FSP_IBUF_HEADER_PAGE_NO,
313
block = buf_page_get(
314
IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
307
315
buf_block_dbg_add_level(block, SYNC_IBUF_HEADER);
309
317
return(buf_block_get_frame(block));
316
324
ibuf_tree_root_get(
317
325
/*===============*/
318
326
/* out: insert buffer tree root page */
319
ibuf_data_t* data, /* in: ibuf data */
320
ulint space, /* in: space id */
321
327
mtr_t* mtr) /* in: mtr */
323
329
buf_block_t* block;
326
331
ut_ad(ibuf_inside());
328
mtr_x_lock(dict_index_get_lock(data->index), mtr);
330
block = buf_page_get(space, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH,
333
mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
335
block = buf_page_get(
336
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
332
338
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
334
340
return(buf_block_get_frame(block));
371
377
/**********************************************************************
378
Updates the size information of the ibuf, assuming the segment size has not
384
const page_t* root, /* in: ibuf tree root */
385
mtr_t* mtr) /* in: mtr */
387
ut_ad(mutex_own(&ibuf_mutex));
389
ibuf->free_list_len = flst_get_len(root + PAGE_HEADER
390
+ PAGE_BTR_IBUF_FREE_LIST, mtr);
392
ibuf->height = 1 + btr_page_get_level(root, mtr);
394
/* the '1 +' is the ibuf header page */
395
ibuf->size = ibuf->seg_size - (1 + ibuf->free_list_len);
397
ibuf->empty = page_get_n_recs(root) == 0;
400
/**********************************************************************
372
401
Creates the insert buffer data structure at a database startup and initializes
373
402
the data structures for the insert buffer. */
376
405
ibuf_init_at_db_start(void)
377
406
/*=======================*/
379
417
ibuf = mem_alloc(sizeof(ibuf_t));
419
memset(ibuf, 0, sizeof(*ibuf));
381
421
/* Note that also a pessimistic delete can sometimes make a B-tree
382
422
grow in size, as the references on the upper levels of the tree can
397
433
mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
399
fil_ibuf_init_at_db_start();
402
/**********************************************************************
403
Updates the size information in an ibuf data, assuming the segment size has
407
ibuf_data_sizes_update(
408
/*===================*/
409
ibuf_data_t* data, /* in: ibuf data struct */
410
const page_t* root, /* in: ibuf tree root */
411
mtr_t* mtr) /* in: mtr */
415
ut_ad(mutex_own(&ibuf_mutex));
417
old_size = data->size;
419
data->free_list_len = flst_get_len(root + PAGE_HEADER
420
+ PAGE_BTR_IBUF_FREE_LIST, mtr);
422
data->height = 1 + btr_page_get_level(root, mtr);
424
data->size = data->seg_size - (1 + data->free_list_len);
425
/* the '1 +' is the ibuf header page */
426
ut_ad(data->size < data->seg_size);
428
if (page_get_n_recs(root) == 0) {
435
ut_ad(ibuf->size + data->size >= old_size);
437
ibuf->size = ibuf->size + data->size - old_size;
440
fprintf(stderr, "ibuf size %lu, space ibuf size %lu\n",
441
ibuf->size, data->size);
445
/**********************************************************************
446
Creates the insert buffer data struct for a single tablespace. Reads the
447
root page of the insert buffer tree in the tablespace. This function can
448
be called only after the dictionary system has been initialized, as this
449
creates also the insert buffer table and index into this tablespace. */
452
ibuf_data_init_for_space(
453
/*=====================*/
454
/* out, own: ibuf data struct, linked to the list
455
in ibuf control structure */
456
ulint space) /* in: space id */
471
data = mem_alloc(sizeof(ibuf_data_t));
477
437
mutex_enter(&ibuf_mutex);
479
mtr_x_lock(fil_space_get_latch(space, NULL), &mtr);
439
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr);
481
header_page = ibuf_header_page_get(space, &mtr);
441
header_page = ibuf_header_page_get(&mtr);
483
443
fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
487
447
ut_ad(n_used >= 2);
489
data->seg_size = n_used;
449
ibuf->seg_size = n_used;
492
buf_block_t* block = buf_page_get(
493
space, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
454
block = buf_page_get(
455
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
494
456
RW_X_LATCH, &mtr);
495
457
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
497
459
root = buf_block_get_frame(block);
503
data->n_merged_recs = 0;
505
ibuf_data_sizes_update(data, root, &mtr);
509
"InnoDB: index entries found in the insert buffer\n");
512
"InnoDB: insert buffer empty\n");
462
ibuf_size_update(root, &mtr);
515
463
mutex_exit(&ibuf_mutex);
517
465
mtr_commit(&mtr);
521
469
heap = mem_heap_create(450);
522
buf = mem_heap_alloc(heap, 50);
524
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
525
/* use old-style record format for the insert buffer */
526
table = dict_mem_table_create(buf, space, 2, 0);
528
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_BINARY, 0, 0);
529
dict_mem_table_add_col(table, heap, "TYPES", DATA_BINARY, 0, 0);
531
table->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
471
/* Use old-style record format for the insert buffer. */
472
table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0);
474
dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0);
476
table->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
533
478
dict_table_add_to_cache(table, heap);
534
479
mem_heap_free(heap);
536
481
index = dict_mem_index_create(
537
buf, "CLUST_IND", space,
538
DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 2);
540
dict_mem_index_add_field(index, "PAGE_NO", 0);
541
dict_mem_index_add_field(index, "TYPES", 0);
543
index->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
482
IBUF_TABLE_NAME, "CLUST_IND",
483
IBUF_SPACE_ID, DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 1);
485
dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
487
index->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
545
489
error = dict_index_add_to_cache(table, index,
546
490
FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
547
491
ut_a(error == DB_SUCCESS);
549
data->index = dict_table_get_first_index(table);
551
mutex_enter(&ibuf_mutex);
553
UT_LIST_ADD_LAST(data_list, ibuf->data_list, data);
555
mutex_exit(&ibuf_mutex);
493
ibuf->index = dict_table_get_first_index(table);
560
496
/*************************************************************************
1040
976
0 for uncompressed pages */
1041
977
ulint page_no)/* in: page number */
1043
return((space == 0 && page_no == IBUF_TREE_ROOT_PAGE_NO)
979
return((space == IBUF_SPACE_ID && page_no == IBUF_TREE_ROOT_PAGE_NO)
1044
980
|| ibuf_bitmap_page(zip_size, page_no));
1047
983
/***************************************************************************
1048
Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. */
984
Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
985
Must not be called when recv_no_ibuf_operations==TRUE. */
1053
990
/* out: TRUE if level 2 or level 3 page */
1054
991
ulint space, /* in: space id */
1055
992
ulint zip_size,/* in: compressed page size in bytes, or 0 */
1056
ulint page_no)/* in: page number */
993
ulint page_no,/* in: page number */
994
mtr_t* mtr) /* in: mtr which will contain an x-latch to the
995
bitmap page if the page is not one of the fixed
996
address ibuf pages, or NULL, in which case a new
997
transaction is created. */
1058
page_t* bitmap_page;
1062
if (recv_no_ibuf_operations) {
1063
/* Recovery is running: no ibuf operations should be
1001
page_t* bitmap_page;
1003
ut_ad(!recv_no_ibuf_operations);
1069
1005
if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
1075
/* Currently we only have an ibuf tree in space 0 */
1008
} else if (space != IBUF_SPACE_ID) {
1080
ut_ad(fil_space_get_type(space) == FIL_TABLESPACE);
1084
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr);
1013
ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
1020
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
1086
1022
ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
1087
IBUF_BITMAP_IBUF, &mtr);
1023
IBUF_BITMAP_IBUF, mtr);
1025
if (mtr == &local_mtr) {
1093
/***************************************************************************
1094
Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. */
1099
/* out: TRUE if level 2 or level 3 page */
1100
ulint space, /* in: space id */
1101
ulint zip_size,/* in: compressed page size in bytes, or 0 */
1102
ulint page_no,/* in: page number */
1103
mtr_t* mtr) /* in: mtr which will contain an x-latch to the
1104
bitmap page if the page is not one of the fixed
1105
address ibuf pages */
1107
page_t* bitmap_page;
1109
if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
1114
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
1116
return(ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
1117
IBUF_BITMAP_IBUF, mtr));
1120
1032
/************************************************************************
1121
1033
Returns the page number field of an ibuf record. */
1249
1161
/*************************************************************************
1250
1162
Builds the entry to insert into a non-clustered index when we have the
1251
1163
corresponding record in an ibuf index. */
1166
ibuf_build_entry_pre_4_1_x(
1167
/*=======================*/
1168
/* out, own: entry to insert to
1169
a non-clustered index; NOTE that
1170
as we copy pointers to fields in
1171
ibuf_rec, the caller must hold a
1172
latch to the ibuf_rec page as long
1173
as the entry is used! */
1174
const rec_t* ibuf_rec, /* in: record in an insert buffer */
1175
mem_heap_t* heap, /* in: heap where built */
1176
dict_index_t** pindex) /* out, own: dummy index that
1177
describes the entry */
1185
ut_a(trx_doublewrite_must_reset_space_ids);
1186
ut_a(!trx_sys_multiple_tablespace_format);
1188
n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
1189
tuple = dtuple_create(heap, n_fields);
1190
types = rec_get_nth_field_old(ibuf_rec, 1, &len);
1192
ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1194
for (i = 0; i < n_fields; i++) {
1198
field = dtuple_get_nth_field(tuple, i);
1200
data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
1202
dfield_set_data(field, data, len);
1204
dtype_read_for_order_and_null_size(
1205
dfield_get_type(field),
1206
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1209
*pindex = ibuf_dummy_index_create(n_fields, FALSE);
1214
/*************************************************************************
1215
Builds the entry to insert into a non-clustered index when we have the
1216
corresponding record in an ibuf index. */
1254
1219
ibuf_build_entry_from_ibuf_rec(
1279
1244
/* This a < 4.1.x format record */
1281
ut_a(trx_doublewrite_must_reset_space_ids);
1282
ut_a(!trx_sys_multiple_tablespace_format);
1284
n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
1285
tuple = dtuple_create(heap, n_fields);
1286
types = rec_get_nth_field_old(ibuf_rec, 1, &len);
1288
ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1290
for (i = 0; i < n_fields; i++) {
1291
field = dtuple_get_nth_field(tuple, i);
1293
data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
1295
dfield_set_data(field, data, len);
1297
dtype_read_for_order_and_null_size(
1298
dfield_get_type(field),
1299
types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1302
*pindex = ibuf_dummy_index_create(n_fields, FALSE);
1246
return(ibuf_build_entry_pre_4_1_x(ibuf_rec, heap, pindex));
1306
1249
/* This a >= 4.1.x format record */
1680
1624
dare to start a pessimistic insert to the insert buffer. */
1683
ibuf_data_enough_free_for_insert(
1684
/*=============================*/
1627
ibuf_data_enough_free_for_insert(void)
1628
/*==================================*/
1685
1629
/* out: TRUE if enough free pages in list */
1686
ibuf_data_t* data) /* in: ibuf data for the space */
1688
1631
ut_ad(mutex_own(&ibuf_mutex));
1701
1644
should remove them and free to the file space management. */
1704
ibuf_data_too_much_free(
1705
/*====================*/
1647
ibuf_data_too_much_free(void)
1648
/*=========================*/
1706
1649
/* out: TRUE if enough free pages in list */
1707
ibuf_data_t* data) /* in: ibuf data for the space */
1709
1651
ut_ad(mutex_own(&ibuf_mutex));
1711
return(data->free_list_len >= 3 + data->size / 2 + 3 * data->height);
1653
return(ibuf->free_list_len >= 3 + (ibuf->size / 2) + 3 * ibuf->height);
1714
1656
/*************************************************************************
1733
1673
page_t* bitmap_page;
1737
1675
mtr_start(&mtr);
1739
1677
/* Acquire the fsp latch before the ibuf header, obeying the latching
1741
mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
1679
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
1742
1680
zip_size = dict_table_flags_to_zip_size(flags);
1744
header_page = ibuf_header_page_get(space, &mtr);
1682
header_page = ibuf_header_page_get(&mtr);
1746
1684
/* Allocate a new page: NOTE that if the page has been a part of a
1747
1685
non-clustered index which has subsequently been dropped, then the
1753
1691
of a deadlock. This is the reason why we created a special ibuf
1754
1692
header page apart from the ibuf tree. */
1756
page_no = fseg_alloc_free_page(header_page + IBUF_HEADER
1757
+ IBUF_TREE_SEG_HEADER, 0, FSP_UP,
1694
page_no = fseg_alloc_free_page(
1695
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
1759
1698
if (page_no == FIL_NULL) {
1760
1699
mtr_commit(&mtr);
1766
buf_block_t* block = buf_page_get(
1767
space, 0, page_no, RW_X_LATCH, &mtr);
1707
block = buf_page_get(
1708
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
1768
1710
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
1770
1713
page = buf_block_get_frame(block);
1784
1727
mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST,
1785
1728
MLOG_2BYTES, &mtr);
1787
ibuf_data->seg_size++;
1788
ibuf_data->free_list_len++;
1731
ibuf->free_list_len++;
1790
1733
/* Set the bit indicating that this page is now an ibuf tree page
1791
1734
(level 2 page) */
1793
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr);
1795
ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
1796
IBUF_BITMAP_IBUF, TRUE, &mtr);
1736
bitmap_page = ibuf_bitmap_get_map_page(
1737
IBUF_SPACE_ID, page_no, zip_size, &mtr);
1739
ibuf_bitmap_page_set_bits(
1740
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
1797
1742
mtr_commit(&mtr);
1799
1744
mutex_exit(&ibuf_mutex);
1823
1766
page_t* bitmap_page;
1827
1768
mtr_start(&mtr);
1829
1770
/* Acquire the fsp latch before the ibuf header, obeying the latching
1831
mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
1772
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
1832
1773
zip_size = dict_table_flags_to_zip_size(flags);
1834
header_page = ibuf_header_page_get(space, &mtr);
1775
header_page = ibuf_header_page_get(&mtr);
1836
1777
/* Prevent pessimistic inserts to insert buffer trees for a while */
1837
1778
mutex_enter(&ibuf_pessimistic_insert_mutex);
1856
1797
mtr_start(&mtr2);
1858
root = ibuf_tree_root_get(ibuf_data, space, &mtr2);
1799
root = ibuf_tree_root_get(&mtr2);
1860
1801
page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
1864
1804
/* NOTE that we must release the latch on the ibuf tree root
1865
1805
because in fseg_free_page we access level 1 pages, and the root
1877
1817
page from it. */
1879
1819
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
1880
space, page_no, &mtr);
1820
IBUF_SPACE_ID, page_no, &mtr);
1881
1822
#ifdef UNIV_DEBUG_FILE_ACCESSES
1882
buf_page_reset_file_page_was_freed(space, page_no);
1823
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
1886
1828
mutex_enter(&ibuf_mutex);
1888
root = ibuf_tree_root_get(ibuf_data, space, &mtr);
1830
root = ibuf_tree_root_get(&mtr);
1890
1832
ut_ad(page_no == flst_get_last(root + PAGE_HEADER
1891
+ PAGE_BTR_IBUF_FREE_LIST, &mtr)
1833
+ PAGE_BTR_IBUF_FREE_LIST, &mtr).page);
1895
buf_block_t* block = buf_page_get(
1896
space, 0, page_no, RW_X_LATCH, &mtr);
1838
block = buf_page_get(
1839
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
1897
1841
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
1899
1844
page = buf_block_get_frame(block);
1904
1849
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
1905
1850
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
1907
ibuf_data->seg_size--;
1908
ibuf_data->free_list_len--;
1853
ibuf->free_list_len--;
1910
1855
mutex_exit(&ibuf_pessimistic_insert_mutex);
1912
1857
/* Set the bit indicating that this page is no more an ibuf tree page
1913
1858
(level 2 page) */
1915
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr);
1917
ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
1918
IBUF_BITMAP_IBUF, FALSE, &mtr);
1860
bitmap_page = ibuf_bitmap_get_map_page(
1861
IBUF_SPACE_ID, page_no, zip_size, &mtr);
1863
ibuf_bitmap_page_set_bits(
1864
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
1919
1866
#ifdef UNIV_DEBUG_FILE_ACCESSES
1920
buf_page_set_file_page_was_freed(space, page_no);
1867
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
1922
1869
mtr_commit(&mtr);
1932
1879
file segment, and the thread did not own the fsp latch before this call. */
1935
ibuf_free_excess_pages(
1936
/*===================*/
1937
ulint space) /* in: compressed page size in bytes, or 0 */
1882
ibuf_free_excess_pages(void)
1883
/*========================*/
1939
ibuf_data_t* ibuf_data;
1944
"InnoDB: Error: calling ibuf_free_excess_pages"
1945
" for space %lu\n", (ulong) space);
1949
1887
#ifdef UNIV_SYNC_DEBUG
1950
ut_ad(rw_lock_own(fil_space_get_latch(space, NULL), RW_LOCK_EX));
1888
ut_ad(rw_lock_own(fil_space_get_latch(IBUF_SPACE_ID, NULL),
1951
1890
#endif /* UNIV_SYNC_DEBUG */
1952
ut_ad(rw_lock_get_x_lock_count(fil_space_get_latch(space, NULL)) == 1);
1892
ut_ad(rw_lock_get_x_lock_count(
1893
fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
1953
1895
ut_ad(!ibuf_inside());
1955
1897
/* NOTE: We require that the thread did not own the latch before,
1956
1898
because then we know that we can obey the correct latching order
1957
1899
for ibuf latches */
1959
ibuf_data = fil_space_get_ibuf_data(space);
1961
if (ibuf_data == NULL) {
1962
/* Not yet initialized */
1964
#if 0 /* defined UNIV_DEBUG */
1966
"Ibuf for space %lu not yet initialized\n", space);
1902
/* Not yet initialized; not sure if this is possible, but
1903
does no harm to check for it. */
2193
2124
ut_ad(!ibuf_inside());
2195
2126
mutex_enter(&ibuf_mutex);
2197
ut_ad(ibuf_validate_low());
2199
/* Choose an ibuf tree at random (though there really is only one tree
2200
in the current implementation) */
2201
ibuf_rnd += 865558671;
2203
rnd_pos = ibuf_rnd % ibuf->size;
2205
all_trees_empty = TRUE;
2207
data = UT_LIST_GET_FIRST(ibuf->data_list);
2211
all_trees_empty = FALSE;
2213
if (rnd_pos < data->size) {
2218
rnd_pos -= data->size;
2221
data = UT_LIST_GET_NEXT(data_list, data);
2224
if (all_trees_empty) {
2225
mutex_exit(&ibuf_mutex);
2230
data = UT_LIST_GET_FIRST(ibuf->data_list);
2130
mutex_exit(&ibuf_mutex);
2236
space = data->index->space;
2238
ut_a(space == 0); /* We currently only have an ibuf tree in
2240
2135
mtr_start(&mtr);
2244
2139
/* Open a cursor to a randomly chosen leaf of the tree, at a random
2245
2140
position within the leaf */
2247
btr_pcur_open_at_rnd_pos(data->index, BTR_SEARCH_LEAF, &pcur, &mtr);
2249
if (0 == page_get_n_recs(btr_pcur_get_page(&pcur))) {
2251
/* This tree is empty */
2142
btr_pcur_open_at_rnd_pos(ibuf->index, BTR_SEARCH_LEAF, &pcur, &mtr);
2144
if (page_get_n_recs(btr_pcur_get_page(&pcur)) == 0) {
2145
/* When the ibuf tree is emptied completely, the last record
2146
is removed using an optimistic delete and ibuf_size_update
2147
is not called, causing ibuf->empty to remain FALSE. If we do
2148
not reset it to TRUE here then database shutdown will hang
2149
in the loop in ibuf_contract_for_n_pages. */
2257
2155
mtr_commit(&mtr);
2258
2156
btr_pcur_close(&pcur);
2260
mutex_exit(&ibuf_mutex);
2265
2161
mutex_exit(&ibuf_mutex);
2453
buf_block_t* block = buf_page_get(
2454
0, 0, prev_page_no, RW_X_LATCH, mtr);
2351
block = buf_page_get(
2352
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
2455
2354
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
2457
2357
prev_page = buf_block_get_frame(block);
2459
2360
#ifdef UNIV_BTR_DEBUG
2460
2361
ut_a(btr_page_get_next(prev_page, mtr)
2461
2362
== page_get_page_no(page));
2522
buf_block_t* block = buf_page_get(
2523
0, 0, next_page_no, RW_X_LATCH, mtr);
2425
block = buf_page_get(
2426
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
2524
2428
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
2526
2431
next_page = buf_block_get_frame(block);
2528
2434
#ifdef UNIV_BTR_DEBUG
2529
ut_a(btr_page_get_prev(next_page, mtr)
2530
== page_get_page_no(page));
2435
ut_a(btr_page_get_prev(next_page, mtr) == page_get_page_no(page));
2531
2436
#endif /* UNIV_BTR_DEBUG */
2533
2438
rec = page_get_infimum_rec(next_page);
2565
2470
const rec_t* rec;
2566
2471
const byte* field;
2568
ibuf_data_t* ibuf_data;
2569
dict_index_t* ibuf_index;
2570
2473
btr_pcur_t pcur;
2573
ibuf_data = fil_space_get_ibuf_data(0);
2575
ibuf_index = ibuf_data->index;
2576
ut_a(!dict_table_is_comp(ibuf_index->table));
2476
ut_a(!dict_table_is_comp(ibuf->index->table));
2580
2480
mtr_start(&mtr);
2582
btr_pcur_open_at_index_side(FALSE, ibuf_index, BTR_SEARCH_LEAF,
2482
btr_pcur_open_at_index_side(
2483
FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
2584
2485
btr_pcur_move_to_prev(&pcur, &mtr);
2586
2487
if (btr_pcur_is_before_first_on_page(&pcur)) {
2727
2619
mtr_start(&mtr);
2729
btr_pcur_open(ibuf_index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
2621
btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
2731
2623
/* Find out the volume of already buffered inserts for the same index
2775
2667
old_bit_value = ibuf_bitmap_page_get_bits(
2776
2668
bitmap_page, page_no, zip_size,
2777
2669
IBUF_BITMAP_BUFFERED, &bitmap_mtr);
2778
2671
if (!old_bit_value) {
2779
2672
ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
2780
2673
IBUF_BITMAP_BUFFERED, TRUE,
3157
3055
#ifdef UNIV_IBUF_COUNT_DEBUG
3158
3056
ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
3160
ibuf_data_sizes_update(ibuf_data, root, mtr);
3162
ut_ad(ibuf_validate_low());
3058
ibuf_size_update(root, mtr);
3164
3061
btr_pcur_commit_specify_mtr(pcur, mtr);
3215
3108
ut_ad(!block || buf_block_get_page_no(block) == page_no);
3216
3109
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
3218
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3223
if (trx_sys_hdr_page(space, page_no)) {
3227
/* The following assumes that the uncompressed page size
3228
is a power-of-2 multiple of zip_size. */
3111
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
3112
|| trx_sys_hdr_page(space, page_no)) {
3116
/* We cannot refer to zip_size in the following, because
3117
zip_size is passed as ULINT_UNDEFINED (it is unknown) when
3118
buf_read_ibuf_merge_pages() is merging (discarding) changes
3119
for a dropped tablespace. When block != NULL or
3120
update_ibuf_bitmap is specified, the zip_size must be known.
3121
That is why we will repeat the check below, with zip_size in
3122
place of 0. Passing zip_size as 0 assumes that the
3123
uncompressed page size always is a power-of-2 multiple of the
3124
compressed page size. */
3229
3126
if (ibuf_fixed_addr_page(space, 0, page_no)
3230
3127
|| fsp_descr_page(0, page_no)) {
3254
3151
update_ibuf_bitmap = FALSE;
3153
page_t* bitmap_page;
3256
3155
mtr_start(&mtr);
3257
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
3157
bitmap_page = ibuf_bitmap_get_map_page(
3158
space, page_no, zip_size, &mtr);
3260
3160
if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
3273
3173
mtr_commit(&mtr);
3276
if (ibuf_fixed_addr_page(space, zip_size, page_no)
3277
|| fsp_descr_page(zip_size, page_no)) {
3176
&& (ibuf_fixed_addr_page(space, zip_size, page_no)
3177
|| fsp_descr_page(zip_size, page_no))) {
3282
/* Currently the insert buffer of space 0 takes care of inserts to all
3285
ibuf_data = fil_space_get_ibuf_data(0);
3289
3184
heap = mem_heap_create(512);
3369
3268
/* Position pcur in the insert buffer at the first entry for this
3371
btr_pcur_open_on_user_rec(ibuf_data->index, search_tuple, PAGE_CUR_GE,
3372
BTR_MODIFY_LEAF, &pcur, &mtr);
3270
btr_pcur_open_on_user_rec(
3271
ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
3373
3274
if (!btr_pcur_is_on_user_rec(&pcur)) {
3374
3275
ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
3380
3283
ut_ad(btr_pcur_is_on_user_rec(&pcur));
3382
ibuf_rec = btr_pcur_get_rec(&pcur);
3285
rec = btr_pcur_get_rec(&pcur);
3384
3287
/* Check if the entry is for this index page */
3385
if (ibuf_rec_get_page_no(ibuf_rec) != page_no
3386
|| ibuf_rec_get_space(ibuf_rec) != space) {
3288
if (ibuf_rec_get_page_no(rec) != page_no
3289
|| ibuf_rec_get_space(rec) != space) {
3388
3292
page_header_reset_last_insert(
3389
3293
block->frame, page_zip, &mtr);
3391
3296
goto reset_bit;
3394
3299
if (UNIV_UNLIKELY(corruption_noticed)) {
3395
3300
fputs("InnoDB: Discarding record\n ", stderr);
3396
rec_print_old(stderr, ibuf_rec);
3301
rec_print_old(stderr, rec);
3397
3302
fputs("\nInnoDB: from the insert buffer!\n\n", stderr);
3398
3303
} else if (block) {
3399
3304
/* Now we have at pcur a record which should be
3400
3305
inserted to the index page; NOTE that the call below
3401
copies pointers to fields in ibuf_rec, and we must
3402
keep the latch to the ibuf_rec page until the
3306
copies pointers to fields in rec, and we must
3307
keep the latch to the rec page until the
3403
3308
insertion is finished! */
3404
3311
dict_index_t* dummy_index;
3405
dulint max_trx_id = page_get_max_trx_id(
3406
page_align(ibuf_rec));
3313
max_trx_id = page_get_max_trx_id(page_align(rec));
3407
3314
page_update_max_trx_id(block, page_zip, max_trx_id);
3409
3316
entry = ibuf_build_entry_from_ibuf_rec(
3410
ibuf_rec, heap, &dummy_index);
3317
rec, heap, &dummy_index);
3411
3318
#ifdef UNIV_IBUF_DEBUG
3412
3319
volume += rec_get_converted_size(dummy_index, entry, 0)
3413
3320
+ page_dir_calc_reserved_space(1);
3448
3353
if (UNIV_LIKELY(update_ibuf_bitmap)) {
3449
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
3451
ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
3452
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
3354
page_t* bitmap_page;
3356
bitmap_page = ibuf_bitmap_get_map_page(
3357
space, page_no, zip_size, &mtr);
3359
ibuf_bitmap_page_set_bits(
3360
bitmap_page, page_no, zip_size,
3361
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
3454
3364
ulint old_bits = ibuf_bitmap_page_get_bits(
3455
3365
bitmap_page, page_no, zip_size,
3456
3366
IBUF_BITMAP_FREE, &mtr);
3457
3368
ulint new_bits = ibuf_index_page_calc_free(
3458
3369
zip_size, block);
3459
#if 0 /* defined UNIV_IBUF_DEBUG */
3460
fprintf(stderr, "Old bits %lu new bits %lu"
3463
page_get_max_insert_size_after_reorganize(
3466
3371
if (old_bits != new_bits) {
3467
ibuf_bitmap_page_set_bits(bitmap_page, page_no,
3372
ibuf_bitmap_page_set_bits(
3373
bitmap_page, page_no, zip_size,
3374
IBUF_BITMAP_FREE, new_bits, &mtr);
3474
#if 0 /* defined UNIV_IBUF_DEBUG */
3476
"Ibuf merge %lu records volume %lu to page no %lu\n",
3477
n_inserts, volume, page_no);
3479
3379
mtr_commit(&mtr);
3480
3380
btr_pcur_close(&pcur);
3481
3381
mem_heap_free(heap);
3541
3436
/* Position pcur in the insert buffer at the first entry for the
3543
btr_pcur_open_on_user_rec(ibuf_data->index, search_tuple, PAGE_CUR_GE,
3544
BTR_MODIFY_LEAF, &pcur, &mtr);
3438
btr_pcur_open_on_user_rec(
3439
ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
3545
3442
if (!btr_pcur_is_on_user_rec(&pcur)) {
3546
3443
ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
3592
3489
/* Protect our statistics keeping from race conditions */
3593
3490
mutex_enter(&ibuf_mutex);
3595
ibuf_data->n_merges++;
3596
ibuf_data->n_merged_recs += n_inserts;
3493
ibuf->n_merged_recs += n_inserts;
3598
3495
mutex_exit(&ibuf_mutex);
3601
"InnoDB: Discarded %lu ibuf entries for space %lu\n",
3602
(ulong) n_inserts, (ulong) space);
3606
3499
mem_heap_free(heap);
3610
/**********************************************************************
3611
Validates the ibuf data structures when the caller owns ibuf_mutex. */
3614
ibuf_validate_low(void)
3615
/*===================*/
3616
/* out: TRUE if ok */
3621
ut_ad(mutex_own(&ibuf_mutex));
3625
data = UT_LIST_GET_FIRST(ibuf->data_list);
3628
sum_sizes += data->size;
3630
data = UT_LIST_GET_NEXT(data_list, data);
3633
ut_a(sum_sizes == ibuf->size);
3637
#endif /* UNIV_DEBUG */
3639
3502
/**********************************************************************
3640
3503
Looks if the insert buffer is empty. */
3654
3516
mutex_enter(&ibuf_mutex);
3656
data = UT_LIST_GET_FIRST(ibuf->data_list);
3658
3518
mtr_start(&mtr);
3660
root = ibuf_tree_root_get(data, 0, &mtr);
3520
root = ibuf_tree_root_get(&mtr);
3662
3522
if (page_get_n_recs(root) == 0) {
3664
3524
is_empty = TRUE;
3666
if (data->empty == FALSE) {
3526
if (ibuf->empty == FALSE) {
3667
3527
fprintf(stderr,
3668
3528
"InnoDB: Warning: insert buffer tree is empty"
3669
3529
" but the data struct does not\n"
3697
3555
FILE* file) /* in: file where to print */
3700
3557
#ifdef UNIV_IBUF_COUNT_DEBUG
3704
3562
mutex_enter(&ibuf_mutex);
3706
data = UT_LIST_GET_FIRST(ibuf->data_list);
3710
"Ibuf: size %lu, free list len %lu, seg size %lu,\n"
3711
"%lu inserts, %lu merged recs, %lu merges\n",
3713
(ulong) data->free_list_len,
3714
(ulong) data->seg_size,
3715
(ulong) data->n_inserts,
3716
(ulong) data->n_merged_recs,
3717
(ulong) data->n_merges);
3565
"Ibuf: size %lu, free list len %lu, seg size %lu,\n"
3566
"%lu inserts, %lu merged recs, %lu merges\n",
3568
(ulong) ibuf->free_list_len,
3569
(ulong) ibuf->seg_size,
3570
(ulong) ibuf->n_inserts,
3571
(ulong) ibuf->n_merged_recs,
3572
(ulong) ibuf->n_merges);
3718
3573
#ifdef UNIV_IBUF_COUNT_DEBUG
3719
for (i = 0; i < IBUF_COUNT_N_PAGES; i++) {
3720
if (ibuf_count_get(data->space, i) > 0) {
3574
for (i = 0; i < IBUF_COUNT_N_SPACES; i++) {
3575
for (j = 0; j < IBUF_COUNT_N_PAGES; j++) {
3576
ulint count = ibuf_count_get(i, j);
3722
3579
fprintf(stderr,
3723
"Ibuf count for page %lu is %lu\n",
3726
ibuf_count_get(data->space, i));
3580
"Ibuf count for space/page %lu/%lu"
3582
(ulong) i, (ulong) j, (ulong) count);
3730
data = UT_LIST_GET_NEXT(data_list, data);
3586
#endif /* UNIV_IBUF_COUNT_DEBUG */
3733
3588
mutex_exit(&ibuf_mutex);