~vlad-lesin/percona-server/pintables

« back to all changes in this revision

Viewing changes to innodb_fake_changes.patch

  • Committer: Laurynas Biveinis
  • Date: 2011-06-21 02:36:36 UTC
  • mfrom: (123 merge)
  • mto: This revision was merged to the branch mainline in revision 124.
  • Revision ID: laurynas.biveinis@percona.com-20110621023636-ccp1iyyrncj181zt
MergeĀ fromĀ lp:percona-server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# name       : innodb_fake_changes.patch
 
2
# introduced : 5.5.12
 
3
# maintainer : Yasufumi
 
4
#
 
5
#!!! notice !!!
 
6
# Any small change to this file in the main branch
 
7
# should be done or reviewed by the maintainer!
 
8
diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
 
9
--- a/storage/innobase/btr/btr0cur.c    2011-06-01 21:04:26.346416429 +0900
 
10
+++ b/storage/innobase/btr/btr0cur.c    2011-06-01 21:04:53.718415294 +0900
 
11
@@ -1167,6 +1167,11 @@
 
12
        rec_t*          rec;
 
13
        roll_ptr_t      roll_ptr;
 
14
 
 
15
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
16
+               /* skip LOCK, UNDO */
 
17
+               return(DB_SUCCESS);
 
18
+       }
 
19
+
 
20
        /* Check if we have to wait for a lock: enqueue an explicit lock
 
21
        request if yes */
 
22
 
 
23
@@ -1298,7 +1303,7 @@
 
24
        }
 
25
 #endif /* UNIV_DEBUG */
 
26
 
 
27
-       ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
28
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
29
        max_size = page_get_max_insert_size_after_reorganize(page, 1);
 
30
        leaf = page_is_leaf(page);
 
31
 
 
32
@@ -1393,6 +1398,12 @@
 
33
                goto fail_err;
 
34
        }
 
35
 
 
36
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
37
+               /* skip CHANGE, LOG */
 
38
+               *big_rec = big_rec_vec;
 
39
+               return(err); /* == DB_SUCCESS */
 
40
+       }
 
41
+
 
42
        page_cursor = btr_cur_get_page_cur(cursor);
 
43
 
 
44
        /* Now, try the insert */
 
45
@@ -1535,10 +1546,10 @@
 
46
 
 
47
        *big_rec = NULL;
 
48
 
 
49
-       ut_ad(mtr_memo_contains(mtr,
 
50
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
 
51
                                dict_index_get_lock(btr_cur_get_index(cursor)),
 
52
                                MTR_MEMO_X_LOCK));
 
53
-       ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
 
54
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
 
55
                                MTR_MEMO_PAGE_X_FIX));
 
56
 
 
57
        /* Try first an optimistic insert; reset the cursor flag: we do not
 
58
@@ -1604,6 +1615,16 @@
 
59
                }
 
60
        }
 
61
 
 
62
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
63
+               /* skip CHANGE, LOG */
 
64
+               if (n_extents > 0) {
 
65
+                       fil_space_release_free_extents(index->space,
 
66
+                                                      n_reserved);
 
67
+               }
 
68
+               *big_rec = big_rec_vec;
 
69
+               return(DB_SUCCESS);
 
70
+       }
 
71
+
 
72
        if (dict_index_get_page(index)
 
73
            == buf_block_get_page_no(btr_cur_get_block(cursor))) {
 
74
 
 
75
@@ -1660,6 +1681,11 @@
 
76
 
 
77
        ut_ad(cursor && update && thr && roll_ptr);
 
78
 
 
79
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
80
+               /* skip LOCK, UNDO */
 
81
+               return(DB_SUCCESS);
 
82
+       }
 
83
+
 
84
        rec = btr_cur_get_rec(cursor);
 
85
        index = cursor->index;
 
86
 
 
87
@@ -1958,6 +1984,14 @@
 
88
                return(err);
 
89
        }
 
90
 
 
91
+       if (trx->fake_changes) {
 
92
+               /* skip CHANGE, LOG */
 
93
+               if (UNIV_LIKELY_NULL(heap)) {
 
94
+                       mem_heap_free(heap);
 
95
+               }
 
96
+               return(err); /* == DB_SUCCESS */
 
97
+       }
 
98
+
 
99
        if (block->is_hashed) {
 
100
                /* The function row_upd_changes_ord_field_binary works only
 
101
                if the update vector was built for a clustered index, we must
 
102
@@ -2061,7 +2095,7 @@
 
103
        rec = btr_cur_get_rec(cursor);
 
104
        index = cursor->index;
 
105
        ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
 
106
-       ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
107
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
108
        /* The insert buffer tree should never be updated in place. */
 
109
        ut_ad(!dict_index_is_ibuf(index));
 
110
 
 
111
@@ -2171,6 +2205,11 @@
 
112
                goto err_exit;
 
113
        }
 
114
 
 
115
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
116
+               /* skip CHANGE, LOG */
 
117
+               goto err_exit; /* == DB_SUCCESS */
 
118
+       }
 
119
+
 
120
        /* Ok, we may do the replacement. Store on the page infimum the
 
121
        explicit locks on rec, before deleting rec (see the comment in
 
122
        btr_cur_pessimistic_update). */
 
123
@@ -2321,9 +2360,9 @@
 
124
        rec = btr_cur_get_rec(cursor);
 
125
        index = cursor->index;
 
126
 
 
127
-       ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
 
128
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
 
129
                                MTR_MEMO_X_LOCK));
 
130
-       ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
131
+       ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
132
 #ifdef UNIV_ZIP_DEBUG
 
133
        ut_a(!page_zip || page_zip_validate(page_zip, page));
 
134
 #endif /* UNIV_ZIP_DEBUG */
 
135
@@ -2411,6 +2450,9 @@
 
136
 
 
137
                ut_ad(big_rec_vec == NULL);
 
138
 
 
139
+               /* fake_changes should not cause undo. so never reaches here */
 
140
+               ut_ad(!(trx->fake_changes));
 
141
+
 
142
                btr_rec_free_updated_extern_fields(
 
143
                        index, rec, page_zip, offsets, update,
 
144
                        trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
 
145
@@ -2445,6 +2487,12 @@
 
146
                }
 
147
        }
 
148
 
 
149
+       if (trx->fake_changes) {
 
150
+               /* skip CHANGE, LOG */
 
151
+               err = DB_SUCCESS;
 
152
+               goto return_after_reservations;
 
153
+       }
 
154
+
 
155
        /* Store state of explicit locks on rec on the page infimum record,
 
156
        before deleting rec. The page infimum acts as a dummy carrier of the
 
157
        locks, taking care also of lock releases, before we can move the locks
 
158
@@ -2746,6 +2794,11 @@
 
159
        ut_ad(dict_index_is_clust(index));
 
160
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
 
161
 
 
162
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
163
+               /* skip LOCK, UNDO, CHANGE, LOG */
 
164
+               return(DB_SUCCESS);
 
165
+       }
 
166
+
 
167
        err = lock_clust_rec_modify_check_and_lock(flags, block,
 
168
                                                   rec, index, offsets, thr);
 
169
 
 
170
@@ -2883,6 +2936,11 @@
 
171
        rec_t*          rec;
 
172
        ulint           err;
 
173
 
 
174
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
175
+               /* skip LOCK, CHANGE, LOG */
 
176
+               return(DB_SUCCESS);
 
177
+       }
 
178
+
 
179
        block = btr_cur_get_block(cursor);
 
180
        rec = btr_cur_get_rec(cursor);
 
181
 
 
182
diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
 
183
--- a/storage/innobase/handler/ha_innodb.cc     2011-06-01 21:04:26.511385596 +0900
 
184
+++ b/storage/innobase/handler/ha_innodb.cc     2011-06-01 21:04:53.723390828 +0900
 
185
@@ -484,6 +484,12 @@
 
186
   " or 2 (write at commit, flush once per second).",
 
187
   NULL, NULL, 1, 0, 2, 0);
 
188
 
 
189
+static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
 
190
+  "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
 
191
+  "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
 
192
+  "ATTENTION: the transaction started after enabled is affected.",
 
193
+  NULL, NULL, FALSE);
 
194
+
 
195
 
 
196
 static handler *innobase_create_handler(handlerton *hton,
 
197
                                         TABLE_SHARE *table,
 
198
@@ -1675,6 +1681,8 @@
 
199
        trx->check_unique_secondary = !thd_test_options(
 
200
                thd, OPTION_RELAXED_UNIQUE_CHECKS);
 
201
 
 
202
+       trx->fake_changes = THDVAR(thd, fake_changes);
 
203
+
 
204
 #ifdef EXTENDED_SLOWLOG
 
205
        if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
 
206
                trx->take_stats = TRUE;
 
207
@@ -7486,12 +7494,20 @@
 
208
 
 
209
        parent_trx = check_trx_exists(thd);
 
210
 
 
211
+
 
212
+       if (parent_trx->fake_changes
 
213
+           && thd_sql_command(thd) != SQLCOM_CREATE_TABLE) {
 
214
+               sql_print_error("innodb_fake_changes cannot treat new table during other than CREATE TABLE. (%s)\n", name);
 
215
+               DBUG_RETURN(HA_ERR_WRONG_COMMAND);
 
216
+       }
 
217
+
 
218
        /* In case MySQL calls this in the middle of a SELECT query, release
 
219
        possible adaptive hash latch to avoid deadlocks of threads */
 
220
 
 
221
        trx_search_latch_release_if_reserved(parent_trx);
 
222
 
 
223
        trx = innobase_trx_allocate(thd);
 
224
+       trx->fake_changes = FALSE;
 
225
 
 
226
        /* Latch the InnoDB data dictionary exclusively so that no deadlocks
 
227
        or lock waits can happen in it during a table create operation.
 
228
@@ -7701,6 +7717,7 @@
 
229
 /*==============================*/
 
230
 {
 
231
        int             error;
 
232
+       ibool           fake_changes_reserved = FALSE;
 
233
 
 
234
        DBUG_ENTER("ha_innobase::truncate");
 
235
 
 
236
@@ -7713,10 +7730,21 @@
 
237
                DBUG_RETURN(HA_ERR_CRASHED);
 
238
        }
 
239
 
 
240
+       if (prebuilt->trx->fake_changes) {
 
241
+               /* disable temporally */
 
242
+               prebuilt->trx->fake_changes = FALSE;
 
243
+               fake_changes_reserved = TRUE;
 
244
+       }
 
245
+
 
246
        /* Truncate the table in InnoDB */
 
247
 
 
248
        error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
 
249
 
 
250
+       if (fake_changes_reserved) {
 
251
+               prebuilt->trx->fake_changes = TRUE;
 
252
+               fake_changes_reserved = FALSE;
 
253
+       }
 
254
+
 
255
        if (share->ib_table->is_corrupt) {
 
256
                DBUG_RETURN(HA_ERR_CRASHED);
 
257
        }
 
258
@@ -7768,6 +7796,7 @@
 
259
        trx_search_latch_release_if_reserved(parent_trx);
 
260
 
 
261
        trx = innobase_trx_allocate(thd);
 
262
+       trx->fake_changes = FALSE;
 
263
 
 
264
        name_len = strlen(name);
 
265
 
 
266
@@ -7855,6 +7884,7 @@
 
267
        trx->mysql_thd = NULL;
 
268
 #else
 
269
        trx = innobase_trx_allocate(thd);
 
270
+       trx->fake_changes = FALSE;
 
271
 #endif
 
272
        row_drop_database_for_mysql(namebuf, trx);
 
273
        my_free(namebuf);
 
274
@@ -7960,6 +7990,7 @@
 
275
        trx_search_latch_release_if_reserved(parent_trx);
 
276
 
 
277
        trx = innobase_trx_allocate(thd);
 
278
+       trx->fake_changes = FALSE;
 
279
 
 
280
        error = innobase_rename_table(trx, from, to, TRUE);
 
281
 
 
282
@@ -12228,6 +12259,7 @@
 
283
   MYSQL_SYSVAR(rollback_segments),
 
284
   MYSQL_SYSVAR(corrupt_table_action),
 
285
   MYSQL_SYSVAR(lazy_drop_table),
 
286
+  MYSQL_SYSVAR(fake_changes),
 
287
   NULL
 
288
 };
 
289
 
 
290
diff -ruN a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
 
291
--- a/storage/innobase/handler/handler0alter.cc 2011-04-11 19:44:03.000000000 +0900
 
292
+++ b/storage/innobase/handler/handler0alter.cc 2011-06-01 21:04:53.728495636 +0900
 
293
@@ -641,6 +641,7 @@
 
294
        ibool           dict_locked     = FALSE;
 
295
        ulint           new_primary;
 
296
        int             error;
 
297
+       ulint           should_fake_changes     = FALSE;
 
298
 
 
299
        DBUG_ENTER("ha_innobase::add_index");
 
300
        ut_a(table);
 
301
@@ -677,11 +678,17 @@
 
302
        }
 
303
 
 
304
        heap = mem_heap_create(1024);
 
305
+
 
306
+       if (prebuilt->trx->fake_changes) {
 
307
+               prebuilt->trx->fake_changes = FALSE;
 
308
+               should_fake_changes = TRUE;
 
309
+       }
 
310
        trx_start_if_not_started(prebuilt->trx);
 
311
 
 
312
        /* Create a background transaction for the operations on
 
313
        the data dictionary tables. */
 
314
        trx = innobase_trx_allocate(user_thd);
 
315
+       trx->fake_changes = FALSE;
 
316
        trx_start_if_not_started(trx);
 
317
 
 
318
        /* Create table containing all indexes to be built in this
 
319
@@ -760,6 +767,9 @@
 
320
                        row_mysql_unlock_data_dictionary(trx);
 
321
                        trx_free_for_mysql(trx);
 
322
                        trx_commit_for_mysql(prebuilt->trx);
 
323
+                       if (should_fake_changes) {
 
324
+                               prebuilt->trx->fake_changes = TRUE;
 
325
+                       }
 
326
                        DBUG_RETURN(error);
 
327
                }
 
328
 
 
329
@@ -925,6 +935,9 @@
 
330
        trx_commit_for_mysql(trx);
 
331
        if (prebuilt->trx) {
 
332
                trx_commit_for_mysql(prebuilt->trx);
 
333
+               if (should_fake_changes) {
 
334
+                       prebuilt->trx->fake_changes = TRUE;
 
335
+               }
 
336
        }
 
337
 
 
338
        if (dict_locked) {
 
339
@@ -1172,6 +1185,7 @@
 
340
        /* Create a background transaction for the operations on
 
341
        the data dictionary tables. */
 
342
        trx = innobase_trx_allocate(user_thd);
 
343
+       trx->fake_changes = FALSE;
 
344
        trx_start_if_not_started(trx);
 
345
 
 
346
        /* Flag this transaction as a dictionary operation, so that
 
347
diff -ruN a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
 
348
--- a/storage/innobase/ibuf/ibuf0ibuf.c 2011-06-01 21:04:26.529383815 +0900
 
349
+++ b/storage/innobase/ibuf/ibuf0ibuf.c 2011-06-01 21:04:53.732416483 +0900
 
350
@@ -3496,6 +3496,8 @@
 
351
 
 
352
        ut_a(trx_sys_multiple_tablespace_format);
 
353
 
 
354
+       ut_ad(!(thr_get_trx(thr)->fake_changes));
 
355
+
 
356
        do_merge = FALSE;
 
357
 
 
358
        /* Perform dirty reads of ibuf->size and ibuf->max_size, to
 
359
diff -ruN a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
 
360
--- a/storage/innobase/include/trx0trx.h        2011-06-01 21:04:25.762416618 +0900
 
361
+++ b/storage/innobase/include/trx0trx.h        2011-06-01 21:04:53.736387944 +0900
 
362
@@ -512,6 +512,7 @@
 
363
                                        FALSE, one can save CPU time and about
 
364
                                        150 bytes in the undo log size as then
 
365
                                        we skip XA steps */
 
366
+       ulint           fake_changes;
 
367
        ulint           flush_log_later;/* In 2PC, we hold the
 
368
                                        prepare_commit mutex across
 
369
                                        both phases. In that case, we
 
370
diff -ruN a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
 
371
--- a/storage/innobase/lock/lock0lock.c 2011-06-01 21:04:26.543396960 +0900
 
372
+++ b/storage/innobase/lock/lock0lock.c 2011-06-01 21:04:53.739416526 +0900
 
373
@@ -3909,6 +3909,10 @@
 
374
 
 
375
        trx = thr_get_trx(thr);
 
376
 
 
377
+       if (trx->fake_changes && mode == LOCK_IX) {
 
378
+               mode = LOCK_IS;
 
379
+       }
 
380
+
 
381
        lock_mutex_enter_kernel();
 
382
 
 
383
        /* Look for stronger locks the same trx already has on the table */
 
384
@@ -5107,6 +5111,11 @@
 
385
        }
 
386
 
 
387
        trx = thr_get_trx(thr);
 
388
+
 
389
+       if (trx->fake_changes) {
 
390
+               return(DB_SUCCESS);
 
391
+       }
 
392
+
 
393
        next_rec = page_rec_get_next_const(rec);
 
394
        next_rec_heap_no = page_rec_get_heap_no(next_rec);
 
395
 
 
396
@@ -5275,6 +5284,10 @@
 
397
                return(DB_SUCCESS);
 
398
        }
 
399
 
 
400
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
401
+               return(DB_SUCCESS);
 
402
+       }
 
403
+
 
404
        heap_no = rec_offs_comp(offsets)
 
405
                ? rec_get_heap_no_new(rec)
 
406
                : rec_get_heap_no_old(rec);
 
407
@@ -5333,6 +5346,10 @@
 
408
                return(DB_SUCCESS);
 
409
        }
 
410
 
 
411
+       if (thr && thr_get_trx(thr)->fake_changes) {
 
412
+               return(DB_SUCCESS);
 
413
+       }
 
414
+
 
415
        heap_no = page_rec_get_heap_no(rec);
 
416
 
 
417
        /* Another transaction cannot have an implicit lock on the record,
 
418
@@ -5420,6 +5437,10 @@
 
419
                return(DB_SUCCESS);
 
420
        }
 
421
 
 
422
+       if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
 
423
+               mode = LOCK_S;
 
424
+       }
 
425
+
 
426
        heap_no = page_rec_get_heap_no(rec);
 
427
 
 
428
        lock_mutex_enter_kernel();
 
429
@@ -5496,6 +5517,10 @@
 
430
                return(DB_SUCCESS);
 
431
        }
 
432
 
 
433
+       if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
 
434
+               mode = LOCK_S;
 
435
+       }
 
436
+
 
437
        heap_no = page_rec_get_heap_no(rec);
 
438
 
 
439
        lock_mutex_enter_kernel();
 
440
diff -ruN a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c
 
441
--- a/storage/innobase/que/que0que.c    2011-06-01 21:04:25.553416889 +0900
 
442
+++ b/storage/innobase/que/que0que.c    2011-06-01 21:04:53.743419001 +0900
 
443
@@ -1417,6 +1417,12 @@
 
444
 
 
445
        ut_a(trx->error_state == DB_SUCCESS);
 
446
 
 
447
+       if (trx->fake_changes) {
 
448
+               /* fake_changes should not access to system tables */
 
449
+               fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
 
450
+               return(DB_ERROR);
 
451
+       }
 
452
+
 
453
        if (reserve_dict_mutex) {
 
454
                mutex_enter(&dict_sys->mutex);
 
455
        }
 
456
diff -ruN a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
 
457
--- a/storage/innobase/row/row0ins.c    2011-06-01 21:04:26.099449453 +0900
 
458
+++ b/storage/innobase/row/row0ins.c    2011-06-01 21:04:53.746383371 +0900
 
459
@@ -1499,6 +1499,11 @@
 
460
        if (UNIV_LIKELY_NULL(heap)) {
 
461
                mem_heap_free(heap);
 
462
        }
 
463
+
 
464
+       if (trx->fake_changes) {
 
465
+               err = DB_SUCCESS;
 
466
+       }
 
467
+
 
468
        return(err);
 
469
 }
 
470
 
 
471
@@ -2004,7 +2009,7 @@
 
472
        }
 
473
 
 
474
        btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
 
475
-                                   search_mode,
 
476
+                                   thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : search_mode,
 
477
                                    &cursor, 0, __FILE__, __LINE__, &mtr);
 
478
 
 
479
        if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
 
480
@@ -2065,7 +2070,7 @@
 
481
 
 
482
                        btr_cur_search_to_nth_level(index, 0, entry,
 
483
                                                    PAGE_CUR_LE,
 
484
-                                                   mode | BTR_INSERT,
 
485
+                                                   thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
 
486
                                                    &cursor, 0,
 
487
                                                    __FILE__, __LINE__, &mtr);
 
488
                }
 
489
@@ -2119,6 +2124,22 @@
 
490
        if (UNIV_LIKELY_NULL(big_rec)) {
 
491
                rec_t*  rec;
 
492
                ulint*  offsets;
 
493
+
 
494
+               if (thr_get_trx(thr)->fake_changes) {
 
495
+                       /* skip store extern */
 
496
+                       if (modify) {
 
497
+                               dtuple_big_rec_free(big_rec);
 
498
+                       } else {
 
499
+                               dtuple_convert_back_big_rec(index, entry, big_rec);
 
500
+                       }
 
501
+
 
502
+                       if (UNIV_LIKELY_NULL(heap)) {
 
503
+                               mem_heap_free(heap);
 
504
+                       }
 
505
+
 
506
+                       return(err);
 
507
+               }
 
508
+
 
509
                mtr_start(&mtr);
 
510
 
 
511
                btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
 
512
diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
 
513
--- a/storage/innobase/row/row0mysql.c  2011-06-01 21:04:26.287385626 +0900
 
514
+++ b/storage/innobase/row/row0mysql.c  2011-06-01 21:04:53.749372325 +0900
 
515
@@ -1245,6 +1245,7 @@
 
516
                prebuilt->table->stat_n_rows--;
 
517
        }
 
518
 
 
519
+       if (!(trx->fake_changes))
 
520
        row_update_statistics_if_needed(prebuilt->table);
 
521
        trx->op_info = "";
 
522
 
 
523
@@ -1504,6 +1505,7 @@
 
524
        that changes indexed columns, UPDATEs that change only non-indexed
 
525
        columns would not affect statistics. */
 
526
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
 
527
+               if (!(trx->fake_changes))
 
528
                row_update_statistics_if_needed(prebuilt->table);
 
529
        }
 
530
 
 
531
@@ -1721,6 +1723,7 @@
 
532
                srv_n_rows_updated++;
 
533
        }
 
534
 
 
535
+       if (!(trx->fake_changes))
 
536
        row_update_statistics_if_needed(table);
 
537
 
 
538
        return(err);
 
539
diff -ruN a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
 
540
--- a/storage/innobase/row/row0upd.c    2011-06-01 21:04:25.588384975 +0900
 
541
+++ b/storage/innobase/row/row0upd.c    2011-06-01 21:04:53.753385366 +0900
 
542
@@ -1603,7 +1603,8 @@
 
543
                mode |= BTR_DELETE_MARK;
 
544
        }
 
545
 
 
546
-       search_result = row_search_index_entry(index, entry, mode,
 
547
+       search_result = row_search_index_entry(index, entry,
 
548
+                                              trx->fake_changes ? BTR_SEARCH_LEAF : mode,
 
549
                                               &pcur, &mtr);
 
550
 
 
551
        btr_cur = btr_pcur_get_btr_cur(&pcur);
 
552
@@ -1850,9 +1851,11 @@
 
553
                the previous invocation of this function. Mark the
 
554
                off-page columns in the entry inherited. */
 
555
 
 
556
+               if (!(trx->fake_changes)) {
 
557
                change_ownership = row_upd_clust_rec_by_insert_inherit(
 
558
                        NULL, NULL, entry, node->update);
 
559
                ut_a(change_ownership);
 
560
+               }
 
561
                /* fall through */
 
562
        case UPD_NODE_INSERT_CLUSTERED:
 
563
                /* A lock wait occurred in row_ins_index_entry() in
 
564
@@ -1882,7 +1885,7 @@
 
565
                delete-marked old record, mark them disowned by the
 
566
                old record and owned by the new entry. */
 
567
 
 
568
-               if (rec_offs_any_extern(offsets)) {
 
569
+               if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
 
570
                        change_ownership = row_upd_clust_rec_by_insert_inherit(
 
571
                                rec, offsets, entry, node->update);
 
572
 
 
573
@@ -2012,7 +2015,8 @@
 
574
        the same transaction do not modify the record in the meantime.
 
575
        Therefore we can assert that the restoration of the cursor succeeds. */
 
576
 
 
577
-       ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
 
578
+       ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
 
579
+                                      pcur, mtr));
 
580
 
 
581
        ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
 
582
                                    dict_table_is_comp(index->table)));
 
583
@@ -2022,7 +2026,8 @@
 
584
                                         node->cmpl_info, thr, mtr);
 
585
        mtr_commit(mtr);
 
586
 
 
587
-       if (err == DB_SUCCESS && big_rec) {
 
588
+       /* skip store extern for fake_changes */
 
589
+       if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
 
590
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
 
591
                rec_t*          rec;
 
592
                rec_offs_init(offsets_);
 
593
@@ -2146,7 +2151,8 @@
 
594
 
 
595
        ut_a(pcur->rel_pos == BTR_PCUR_ON);
 
596
 
 
597
-       success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
 
598
+       success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
 
599
+                                           pcur, mtr);
 
600
 
 
601
        if (!success) {
 
602
                err = DB_RECORD_NOT_FOUND;
 
603
diff -ruN a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
 
604
--- a/storage/innobase/trx/trx0trx.c    2011-06-01 21:04:26.411537237 +0900
 
605
+++ b/storage/innobase/trx/trx0trx.c    2011-06-01 21:04:53.756415956 +0900
 
606
@@ -121,6 +121,8 @@
 
607
 
 
608
        trx->support_xa = TRUE;
 
609
 
 
610
+       trx->fake_changes = FALSE;
 
611
+
 
612
        trx->check_foreigns = TRUE;
 
613
        trx->check_unique_secondary = TRUE;
 
614