Skip to content

Commit 67da9e8

Browse files
author
Sergei Golubchik
committed
5.6.22-71.0
1 parent b1e84da commit 67da9e8

27 files changed

+781
-273
lines changed

btr/btr0cur.cc

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,6 +2518,38 @@ btr_cur_pess_upd_restore_supremum(
25182518
page_rec_get_heap_no(rec));
25192519
}
25202520

2521+
/*************************************************************//**
2522+
Check if the total length of the modified blob for the row is within 10%
2523+
of the total redo log size. This constraint on the blob length is to
2524+
avoid overwriting the redo logs beyond the last checkpoint lsn.
2525+
@return DB_SUCCESS or DB_TOO_BIG_RECORD. */
2526+
static
2527+
dberr_t
2528+
btr_check_blob_limit(const big_rec_t* big_rec_vec)
2529+
{
2530+
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
2531+
* UNIV_PAGE_SIZE;
2532+
const ulint redo_10p = redo_size / 10;
2533+
ulint total_blob_len = 0;
2534+
dberr_t err = DB_SUCCESS;
2535+
2536+
/* Calculate the total number of bytes for blob data */
2537+
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
2538+
total_blob_len += big_rec_vec->fields[i].len;
2539+
}
2540+
2541+
if (total_blob_len > redo_10p) {
2542+
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
2543+
" length (" ULINTPF ") is greater than"
2544+
" 10%% of the total redo log size (" UINT64PF
2545+
"). Please increase total redo log size.",
2546+
total_blob_len, redo_size);
2547+
err = DB_TOO_BIG_RECORD;
2548+
}
2549+
2550+
return(err);
2551+
}
2552+
25212553
/*************************************************************//**
25222554
Performs an update of a record on a page of a tree. It is assumed
25232555
that mtr holds an x-latch on the tree and on the cursor page. If the
@@ -2756,26 +2788,14 @@ btr_cur_pessimistic_update(
27562788
}
27572789

27582790
if (big_rec_vec) {
2759-
const ulint redo_10p = srv_log_file_size * UNIV_PAGE_SIZE / 10;
2760-
ulint total_blob_len = 0;
27612791

2762-
/* Calculate the total number of bytes for blob data */
2763-
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
2764-
total_blob_len += big_rec_vec->fields[i].len;
2765-
}
2792+
err = btr_check_blob_limit(big_rec_vec);
27662793

2767-
if (total_blob_len > redo_10p) {
2768-
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
2769-
" length (" ULINTPF ") is greater than"
2770-
" 10%% of the redo log file size (" UINT64PF
2771-
"). Please increase innodb_log_file_size.",
2772-
total_blob_len, srv_log_file_size);
2794+
if (err != DB_SUCCESS) {
27732795
if (n_reserved > 0) {
27742796
fil_space_release_free_extents(
27752797
index->space, n_reserved);
27762798
}
2777-
2778-
err = DB_TOO_BIG_RECORD;
27792799
goto err_exit;
27802800
}
27812801
}
@@ -4630,7 +4650,6 @@ btr_store_big_rec_extern_fields(
46304650
buf_block_t** freed_pages = NULL;
46314651
ulint n_freed_pages = 0;
46324652
dberr_t error = DB_SUCCESS;
4633-
ulint total_blob_len = 0;
46344653

46354654
ut_ad(rec_offs_validate(rec, index, offsets));
46364655
ut_ad(rec_offs_any_extern(offsets));
@@ -4650,21 +4669,11 @@ btr_store_big_rec_extern_fields(
46504669
rec_page_no = buf_block_get_page_no(rec_block);
46514670
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
46524671

4653-
const ulint redo_10p = (srv_log_file_size * UNIV_PAGE_SIZE / 10);
4672+
error = btr_check_blob_limit(big_rec_vec);
46544673

4655-
/* Calculate the total number of bytes for blob data */
4656-
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
4657-
total_blob_len += big_rec_vec->fields[i].len;
4658-
}
4659-
4660-
if (total_blob_len > redo_10p) {
4674+
if (error != DB_SUCCESS) {
46614675
ut_ad(op == BTR_STORE_INSERT);
4662-
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data length"
4663-
" (" ULINTPF ") is greater than 10%% of the"
4664-
" redo log file size (" UINT64PF "). Please"
4665-
" increase innodb_log_file_size.",
4666-
total_blob_len, srv_log_file_size);
4667-
return(DB_TOO_BIG_RECORD);
4676+
return(error);
46684677
}
46694678

46704679
if (page_zip) {

buf/buf0buf.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,14 @@ buf_page_is_corrupted(
592592
checksum_field2 = mach_read_from_4(
593593
read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
594594

595+
#if FIL_PAGE_LSN % 8
596+
#error "FIL_PAGE_LSN must be 64 bit aligned"
597+
#endif
598+
595599
/* declare empty pages non-corrupted */
596600
if (checksum_field1 == 0 && checksum_field2 == 0
597-
&& mach_read_from_4(read_buf + FIL_PAGE_LSN) == 0) {
601+
&& *reinterpret_cast<const ib_uint64_t*>(read_buf +
602+
FIL_PAGE_LSN) == 0) {
598603
/* make sure that the page is really empty */
599604
for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) {
600605
if (read_buf[i] != 0) {
@@ -1649,8 +1654,9 @@ buf_pool_watch_is_sentinel(
16491654

16501655
/****************************************************************//**
16511656
Add watch for the given page to be read in. Caller must have
1652-
appropriate hash_lock for the bpage. This function may release the
1653-
hash_lock and reacquire it.
1657+
appropriate hash_lock for the bpage and hold the LRU list mutex to avoid a race
1658+
condition with buf_LRU_free_page inserting the same page into the page hash.
1659+
This function may release the hash_lock and reacquire it.
16541660
@return NULL if watch set, block if the page is in the buffer pool */
16551661
UNIV_INTERN
16561662
buf_page_t*
@@ -1665,6 +1671,8 @@ buf_pool_watch_set(
16651671
buf_pool_t* buf_pool = buf_pool_get(space, offset);
16661672
prio_rw_lock_t* hash_lock;
16671673

1674+
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
1675+
16681676
hash_lock = buf_page_hash_lock_get(buf_pool, fold);
16691677

16701678
#ifdef UNIV_SYNC_DEBUG
@@ -1733,6 +1741,7 @@ buf_pool_watch_set(
17331741
bpage->space = static_cast<ib_uint32_t>(space);
17341742
bpage->offset = static_cast<ib_uint32_t>(offset);
17351743
bpage->buf_fix_count = 1;
1744+
bpage->buf_pool_index = buf_pool_index(buf_pool);
17361745

17371746
mutex_exit(&buf_pool->zip_mutex);
17381747

@@ -2678,9 +2687,11 @@ buf_page_get_gen(
26782687
/* Page not in buf_pool: needs to be read from file */
26792688

26802689
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2690+
mutex_enter(&buf_pool->LRU_list_mutex);
26812691
rw_lock_x_lock(hash_lock);
26822692
block = (buf_block_t*) buf_pool_watch_set(
26832693
space, offset, fold);
2694+
mutex_exit(&buf_pool->LRU_list_mutex);
26842695

26852696
if (UNIV_LIKELY_NULL(block)) {
26862697
/* We can release hash_lock after we
@@ -3012,15 +3023,19 @@ buf_page_get_gen(
30123023
if (buf_LRU_free_page(&fix_block->page, true)) {
30133024

30143025
mutex_exit(fix_mutex);
3015-
rw_lock_x_lock(hash_lock);
30163026

30173027
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
3028+
mutex_enter(&buf_pool->LRU_list_mutex);
3029+
rw_lock_x_lock(hash_lock);
3030+
30183031
/* Set the watch, as it would have
30193032
been set if the page were not in the
30203033
buffer pool in the first place. */
30213034
block = (buf_block_t*) buf_pool_watch_set(
30223035
space, offset, fold);
3036+
mutex_exit(&buf_pool->LRU_list_mutex);
30233037
} else {
3038+
rw_lock_x_lock(hash_lock);
30243039
block = (buf_block_t*) buf_page_hash_get_low(
30253040
buf_pool, space, offset, fold);
30263041
}

buf/buf0flu.cc

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -836,39 +836,35 @@ buf_flush_init_for_writing(
836836
case SRV_CHECKSUM_ALGORITHM_CRC32:
837837
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
838838
checksum = buf_calc_page_crc32(page);
839+
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
839840
break;
840841
case SRV_CHECKSUM_ALGORITHM_INNODB:
841842
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
842843
checksum = (ib_uint32_t) buf_calc_page_new_checksum(page);
844+
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
845+
checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
843846
break;
844847
case SRV_CHECKSUM_ALGORITHM_NONE:
845848
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
846849
checksum = BUF_NO_CHECKSUM_MAGIC;
850+
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
847851
break;
848852
/* no default so the compiler will emit a warning if new enum
849853
is added and not handled here */
850854
}
851855

852-
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
853-
854-
/* We overwrite the first 4 bytes of the end lsn field to store
855-
the old formula checksum. Since it depends also on the field
856-
FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the
857-
new formula checksum. */
858-
859-
if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB
860-
|| srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) {
856+
/* With the InnoDB checksum, we overwrite the first 4 bytes of
857+
the end lsn field to store the old formula checksum. Since it
858+
depends also on the field FIL_PAGE_SPACE_OR_CHKSUM, it has to
859+
be calculated after storing the new formula checksum.
861860
862-
checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
863-
864-
/* In other cases we use the value assigned from above.
865-
If CRC32 is used then it is faster to use that checksum
866-
(calculated above) instead of calculating another one.
867-
We can afford to store something other than
868-
buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
869-
this field because the file will not be readable by old
870-
versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
871-
}
861+
In other cases we write the same value to both fields.
862+
If CRC32 is used then it is faster to use that checksum
863+
(calculated above) instead of calculating another one.
864+
We can afford to store something other than
865+
buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
866+
this field because the file will not be readable by old
867+
versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
872868

873869
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
874870
checksum);

dict/dict0dict.cc

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ UNIV_INTERN dict_index_t* dict_ind_redundant;
3939
/** dummy index for ROW_FORMAT=COMPACT supremum and infimum records */
4040
UNIV_INTERN dict_index_t* dict_ind_compact;
4141

42+
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
43+
/** Flag to control insert buffer debugging. */
44+
extern UNIV_INTERN uint ibuf_debug;
45+
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
46+
47+
/**********************************************************************
48+
Issue a warning that the row is too big. */
49+
void
50+
ib_warn_row_too_big(const dict_table_t* table);
51+
4252
#ifndef UNIV_HOTBACKUP
4353
#include "buf0buf.h"
4454
#include "data0type.h"
@@ -2406,11 +2416,18 @@ dict_index_add_to_cache(
24062416
new_index->n_fields = new_index->n_def;
24072417
new_index->trx_id = index->trx_id;
24082418

2409-
if (strict && dict_index_too_big_for_tree(table, new_index)) {
2419+
if (dict_index_too_big_for_tree(table, new_index)) {
2420+
2421+
if (strict) {
24102422
too_big:
2411-
dict_mem_index_free(new_index);
2412-
dict_mem_index_free(index);
2413-
return(DB_TOO_BIG_RECORD);
2423+
dict_mem_index_free(new_index);
2424+
dict_mem_index_free(index);
2425+
return(DB_TOO_BIG_RECORD);
2426+
} else {
2427+
2428+
ib_warn_row_too_big(table);
2429+
2430+
}
24142431
}
24152432

24162433
if (dict_index_is_univ(index)) {
@@ -5683,11 +5700,11 @@ dict_set_corrupted(
56835700

56845701
dict_index_copy_types(tuple, sys_index, 2);
56855702

5686-
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
5703+
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
56875704
BTR_MODIFY_LEAF,
56885705
&cursor, 0, __FILE__, __LINE__, &mtr);
56895706

5690-
if (cursor.up_match == dtuple_get_n_fields(tuple)) {
5707+
if (cursor.low_match == dtuple_get_n_fields(tuple)) {
56915708
/* UPDATE SYS_INDEXES SET TYPE=index->type
56925709
WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
56935710
ulint len;

fil/fil0fil.cc

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,7 +2139,8 @@ UNIV_INTERN
21392139
ibool
21402140
fil_inc_pending_ops(
21412141
/*================*/
2142-
ulint id) /*!< in: space id */
2142+
ulint id, /*!< in: space id */
2143+
ibool print_err) /*!< in: need to print error or not */
21432144
{
21442145
fil_space_t* space;
21452146

@@ -2148,10 +2149,12 @@ fil_inc_pending_ops(
21482149
space = fil_space_get_by_id(id);
21492150

21502151
if (space == NULL) {
2151-
fprintf(stderr,
2152-
"InnoDB: Error: trying to do an operation on a"
2153-
" dropped tablespace %lu\n",
2154-
(ulong) id);
2152+
if (print_err) {
2153+
fprintf(stderr,
2154+
"InnoDB: Error: trying to do an operation on a"
2155+
" dropped tablespace %lu\n",
2156+
(ulong) id);
2157+
}
21552158
}
21562159

21572160
if (space == NULL || space->stop_new_ops) {
@@ -4300,7 +4303,18 @@ fil_load_single_table_tablespace(
43004303
/* Build up the tablename in the standard form database/table. */
43014304
tablename = static_cast<char*>(
43024305
mem_alloc(dbname_len + filename_len + 2));
4303-
sprintf(tablename, "%s/%s", dbname, filename);
4306+
4307+
/* When lower_case_table_names = 2 it is possible that the
4308+
dbname is in upper case ,but while storing it in fil_space_t
4309+
we must convert it into lower case */
4310+
sprintf(tablename, "%s" , dbname);
4311+
tablename[dbname_len] = '\0';
4312+
4313+
if (lower_case_file_system) {
4314+
dict_casedn_str(tablename);
4315+
}
4316+
4317+
sprintf(tablename+dbname_len,"/%s",filename);
43044318
tablename_len = strlen(tablename) - strlen(".ibd");
43054319
tablename[tablename_len] = '\0';
43064320

0 commit comments

Comments
 (0)