~tsarev/percona-server/5.5-processlist_rows_stats-sporadic_fails-fix

111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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,
118 by kinoyasu
port Yasufumi patches to 5.5.13
198
@@ -1675,6 +1681,8 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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;
118 by kinoyasu
port Yasufumi patches to 5.5.13
207
@@ -7486,12 +7494,20 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
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 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
229
 /*==============================*/
230
 {
231
 	int		error;
232
+	ibool		fake_changes_reserved = FALSE;
233
 
234
 	DBUG_ENTER("ha_innobase::truncate");
235
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
236
@@ -7713,10 +7730,21 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 	}
118 by kinoyasu
port Yasufumi patches to 5.5.13
258
@@ -7768,6 +7796,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
259
 	trx_search_latch_release_if_reserved(parent_trx);
260
 
261
 	trx = innobase_trx_allocate(thd);
262
+	trx->fake_changes = FALSE;
263
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
264
 	name_len = strlen(name);
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
265
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
266
@@ -7855,6 +7884,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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);
118 by kinoyasu
port Yasufumi patches to 5.5.13
274
@@ -7960,6 +7990,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
282
@@ -12228,6 +12259,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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);
118 by kinoyasu
port Yasufumi patches to 5.5.13
301
@@ -677,11 +678,17 @@
302
 	}
303
 
304
 	heap = mem_heap_create(1024);
305
+
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
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
 		}
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
328
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
329
@@ -925,6 +935,9 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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) {
118 by kinoyasu
port Yasufumi patches to 5.5.13
339
@@ -1172,6 +1185,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
118 by kinoyasu
port Yasufumi patches to 5.5.13
350
@@ -3496,6 +3496,8 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
118 by kinoyasu
port Yasufumi patches to 5.5.13
362
@@ -512,6 +512,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
118 by kinoyasu
port Yasufumi patches to 5.5.13
515
@@ -1245,6 +1245,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
523
@@ -1504,6 +1505,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
 
118 by kinoyasu
port Yasufumi patches to 5.5.13
531
@@ -1721,6 +1723,7 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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
118 by kinoyasu
port Yasufumi patches to 5.5.13
606
@@ -121,6 +121,8 @@
111.2.1 by kinoyasu
innodb_fake_changes.patch is added
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