Merge lp:~percona-dev/percona-server/5.1.57-innodb_fake_changes into lp:~percona-dev/percona-server/5.1.57

Proposed by Yasufumi Kinoshita
Status: Merged
Merge reported by: Stewart Smith
Merged at revision: not available
Proposed branch: lp:~percona-dev/percona-server/5.1.57-innodb_fake_changes
Merge into: lp:~percona-dev/percona-server/5.1.57
Diff against target: 631 lines (+616/-0)
2 files modified
innodb_fake_changes.patch (+615/-0)
series (+1/-0)
To merge this branch: bzr merge lp:~percona-dev/percona-server/5.1.57-innodb_fake_changes
Reviewer Review Type Date Requested Status
Vadim Tkachenko Abstain
Stewart Smith Pending
Review via email: mp+63106@code.launchpad.net

Description of the change

- new boolean session variable 'innodb_fake_changes'

- effect for DML only
------ UPDATE, INSERT, REPLACE, DELETE(set deleted flag), etc...
------ "not" for DDL (ALTER TABLE, TRUNCATE TABLE etc)

- return error for some DDLs, because couldn't control perfectly.

- never acquire X_LOCK of table, rec. S_LOCK only (intended, at least)

- the auto increment values behaves as usual.

- might be dangerous if you use not-tested DDL.
------ fake_changes could be disabled temporally for DDL. otherwise, data should be lost.
------ if fail to port in future, or if you extended DDL by yourself, it may lose the consistency of the dictionary.

- doesn't use ibuf
------ INSERT always causes the reading of the page actually for the option

- reserve free pages as usual
------ may extend the file size and add new extent (may update INODE page)

- existed btr pages only
------ only "root ~ leaf" pages, which are accessed in the DML

------ "not" allocate/free split/merge pages
---------------- not prefetch INODE, XDES or other management pages.

------ "not" extern pages (large BLOB > about 750 length?)
---------------- (delete extern is done by purge, not by DML)

- the effective unit is each transaction
------ the behavior is decided at the start of the trx.
------ never changed during the transaction.

- the foreign key constraint is checked (for cause io), but passed always

To post a comment you must log in.
Revision history for this message
Vadim Tkachenko (vadim-tk) wrote :

I assign it to stewart, the feature should have test and documentation

review: Abstain
Revision history for this message
Yasufumi Kinoshita (yasufumi-kinoshita) wrote :

This MP is just remained for memo.
It will be merged when porting to 5.1.58.
After that this MP will be removed.

Revision history for this message
Stewart Smith (stewart) wrote :

marking as merged as we have merged the feature into lp:percona-server/5.1

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'innodb_fake_changes.patch'
2--- innodb_fake_changes.patch 1970-01-01 00:00:00 +0000
3+++ innodb_fake_changes.patch 2011-06-01 12:17:31 +0000
4@@ -0,0 +1,615 @@
5+# name : innodb_fake_changes.patch
6+# introduced : 5.1.57
7+# maintainer : Yasufumi
8+#
9+#!!! notice !!!
10+# Any small change to this file in the main branch
11+# should be done or reviewed by the maintainer!
12+diff -ruN a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
13+--- a/storage/innodb_plugin/btr/btr0cur.c 2011-06-01 20:53:22.080536658 +0900
14++++ b/storage/innodb_plugin/btr/btr0cur.c 2011-06-01 20:53:47.840384069 +0900
15+@@ -1046,6 +1046,11 @@
16+ rec_t* rec;
17+ roll_ptr_t roll_ptr;
18+
19++ if (thr && thr_get_trx(thr)->fake_changes) {
20++ /* skip LOCK, UNDO */
21++ return(DB_SUCCESS);
22++ }
23++
24+ /* Check if we have to wait for a lock: enqueue an explicit lock
25+ request if yes */
26+
27+@@ -1177,7 +1182,7 @@
28+ }
29+ #endif /* UNIV_DEBUG */
30+
31+- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
32++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
33+ max_size = page_get_max_insert_size_after_reorganize(page, 1);
34+ leaf = page_is_leaf(page);
35+
36+@@ -1272,6 +1277,12 @@
37+ goto fail_err;
38+ }
39+
40++ if (thr && thr_get_trx(thr)->fake_changes) {
41++ /* skip CHANGE, LOG */
42++ *big_rec = big_rec_vec;
43++ return(err); /* == DB_SUCCESS */
44++ }
45++
46+ page_cursor = btr_cur_get_page_cur(cursor);
47+
48+ /* Now, try the insert */
49+@@ -1414,10 +1425,10 @@
50+
51+ *big_rec = NULL;
52+
53+- ut_ad(mtr_memo_contains(mtr,
54++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
55+ dict_index_get_lock(btr_cur_get_index(cursor)),
56+ MTR_MEMO_X_LOCK));
57+- ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
58++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
59+ MTR_MEMO_PAGE_X_FIX));
60+
61+ /* Try first an optimistic insert; reset the cursor flag: we do not
62+@@ -1483,6 +1494,16 @@
63+ }
64+ }
65+
66++ if (thr && thr_get_trx(thr)->fake_changes) {
67++ /* skip CHANGE, LOG */
68++ if (n_extents > 0) {
69++ fil_space_release_free_extents(index->space,
70++ n_reserved);
71++ }
72++ *big_rec = big_rec_vec;
73++ return(DB_SUCCESS);
74++ }
75++
76+ if (dict_index_get_page(index)
77+ == buf_block_get_page_no(btr_cur_get_block(cursor))) {
78+
79+@@ -1539,6 +1560,11 @@
80+
81+ ut_ad(cursor && update && thr && roll_ptr);
82+
83++ if (thr && thr_get_trx(thr)->fake_changes) {
84++ /* skip LOCK, UNDO */
85++ return(DB_SUCCESS);
86++ }
87++
88+ rec = btr_cur_get_rec(cursor);
89+ index = cursor->index;
90+
91+@@ -1837,6 +1863,14 @@
92+ return(err);
93+ }
94+
95++ if (trx->fake_changes) {
96++ /* skip CHANGE, LOG */
97++ if (UNIV_LIKELY_NULL(heap)) {
98++ mem_heap_free(heap);
99++ }
100++ return(err); /* == DB_SUCCESS */
101++ }
102++
103+ if (block->is_hashed) {
104+ /* The function row_upd_changes_ord_field_binary works only
105+ if the update vector was built for a clustered index, we must
106+@@ -1940,7 +1974,7 @@
107+ rec = btr_cur_get_rec(cursor);
108+ index = cursor->index;
109+ ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
110+- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
111++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
112+ /* The insert buffer tree should never be updated in place. */
113+ ut_ad(!dict_index_is_ibuf(index));
114+
115+@@ -2050,6 +2084,11 @@
116+ goto err_exit;
117+ }
118+
119++ if (thr && thr_get_trx(thr)->fake_changes) {
120++ /* skip CHANGE, LOG */
121++ goto err_exit; /* == DB_SUCCESS */
122++ }
123++
124+ /* Ok, we may do the replacement. Store on the page infimum the
125+ explicit locks on rec, before deleting rec (see the comment in
126+ btr_cur_pessimistic_update). */
127+@@ -2200,9 +2239,9 @@
128+ rec = btr_cur_get_rec(cursor);
129+ index = cursor->index;
130+
131+- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
132++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
133+ MTR_MEMO_X_LOCK));
134+- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
135++ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
136+ #ifdef UNIV_ZIP_DEBUG
137+ ut_a(!page_zip || page_zip_validate(page_zip, page));
138+ #endif /* UNIV_ZIP_DEBUG */
139+@@ -2290,6 +2329,9 @@
140+
141+ ut_ad(big_rec_vec == NULL);
142+
143++ /* fake_changes should not cause undo. so never reaches here */
144++ ut_ad(!(trx->fake_changes));
145++
146+ btr_rec_free_updated_extern_fields(
147+ index, rec, page_zip, offsets, update,
148+ trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
149+@@ -2324,6 +2366,12 @@
150+ }
151+ }
152+
153++ if (trx->fake_changes) {
154++ /* skip CHANGE, LOG */
155++ err = DB_SUCCESS;
156++ goto return_after_reservations;
157++ }
158++
159+ /* Store state of explicit locks on rec on the page infimum record,
160+ before deleting rec. The page infimum acts as a dummy carrier of the
161+ locks, taking care also of lock releases, before we can move the locks
162+@@ -2625,6 +2673,11 @@
163+ ut_ad(dict_index_is_clust(index));
164+ ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
165+
166++ if (thr && thr_get_trx(thr)->fake_changes) {
167++ /* skip LOCK, UNDO, CHANGE, LOG */
168++ return(DB_SUCCESS);
169++ }
170++
171+ err = lock_clust_rec_modify_check_and_lock(flags, block,
172+ rec, index, offsets, thr);
173+
174+@@ -2762,6 +2815,11 @@
175+ rec_t* rec;
176+ ulint err;
177+
178++ if (thr && thr_get_trx(thr)->fake_changes) {
179++ /* skip LOCK, CHANGE, LOG */
180++ return(DB_SUCCESS);
181++ }
182++
183+ block = btr_cur_get_block(cursor);
184+ rec = btr_cur_get_rec(cursor);
185+
186+diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
187+--- a/storage/innodb_plugin/handler/ha_innodb.cc 2011-06-01 20:53:22.812388119 +0900
188++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2011-06-01 20:53:47.848787344 +0900
189+@@ -368,6 +368,12 @@
190+ "The value 3 regards innodb_flush_log_at_trx_commit (default).",
191+ NULL, NULL, 3, 0, 3, 0);
192+
193++static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
194++ "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
195++ "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
196++ "ATTENTION: the transaction started after enabled is affected.",
197++ NULL, NULL, FALSE);
198++
199+
200+ static handler *innobase_create_handler(handlerton *hton,
201+ TABLE_SHARE *table,
202+@@ -1399,6 +1405,8 @@
203+ trx->check_unique_secondary = !thd_test_options(
204+ thd, OPTION_RELAXED_UNIQUE_CHECKS);
205+
206++ trx->fake_changes = THDVAR(thd, fake_changes);
207++
208+ #ifdef EXTENDED_SLOWLOG
209+ if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
210+ trx->take_stats = TRUE;
211+@@ -6984,12 +6992,20 @@
212+
213+ parent_trx = check_trx_exists(thd);
214+
215++
216++ if (parent_trx->fake_changes
217++ && thd_sql_command(thd) != SQLCOM_CREATE_TABLE) {
218++ sql_print_error("innodb_fake_changes cannot treat new table during other than CREATE TABLE. (%s)\n", name);
219++ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
220++ }
221++
222+ /* In case MySQL calls this in the middle of a SELECT query, release
223+ possible adaptive hash latch to avoid deadlocks of threads */
224+
225+ trx_search_latch_release_if_reserved(parent_trx);
226+
227+ trx = innobase_trx_allocate(thd);
228++ trx->fake_changes = FALSE;
229+
230+ if (lower_case_table_names) {
231+ srv_lower_case_table_names = TRUE;
232+@@ -7345,6 +7361,7 @@
233+ /*==============================*/
234+ {
235+ int error;
236++ ibool fake_changes_reserved = FALSE;
237+
238+ DBUG_ENTER("ha_innobase::delete_all_rows");
239+
240+@@ -7365,9 +7382,21 @@
241+ DBUG_RETURN(HA_ERR_CRASHED);
242+ }
243+
244++ if (prebuilt->trx->fake_changes) {
245++ /* disable temporally */
246++ prebuilt->trx->fake_changes = FALSE;
247++ fake_changes_reserved = TRUE;
248++ }
249++
250+ /* Truncate the table in InnoDB */
251+
252+ error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
253++
254++ if (fake_changes_reserved) {
255++ prebuilt->trx->fake_changes = TRUE;
256++ fake_changes_reserved = FALSE;
257++ }
258++
259+ if (error == DB_ERROR) {
260+ /* Cannot truncate; resort to ha_innobase::delete_row() */
261+ goto fallback;
262+@@ -7424,6 +7453,7 @@
263+ trx_search_latch_release_if_reserved(parent_trx);
264+
265+ trx = innobase_trx_allocate(thd);
266++ trx->fake_changes = FALSE;
267+
268+ if (lower_case_table_names) {
269+ srv_lower_case_table_names = TRUE;
270+@@ -7517,6 +7547,7 @@
271+ trx->mysql_thd = NULL;
272+ #else
273+ trx = innobase_trx_allocate(thd);
274++ trx->fake_changes = FALSE;
275+ #endif
276+ row_drop_database_for_mysql(namebuf, trx);
277+ my_free(namebuf, MYF(0));
278+@@ -7628,6 +7659,7 @@
279+ trx_search_latch_release_if_reserved(parent_trx);
280+
281+ trx = innobase_trx_allocate(thd);
282++ trx->fake_changes = FALSE;
283+
284+ error = innobase_rename_table(trx, from, to, TRUE);
285+
286+@@ -11862,6 +11894,7 @@
287+ MYSQL_SYSVAR(use_purge_thread),
288+ MYSQL_SYSVAR(pass_corrupt_table),
289+ MYSQL_SYSVAR(lazy_drop_table),
290++ MYSQL_SYSVAR(fake_changes),
291+ NULL
292+ };
293+
294+diff -ruN a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
295+--- a/storage/innodb_plugin/handler/handler0alter.cc 2011-04-12 21:11:39.000000000 +0900
296++++ b/storage/innodb_plugin/handler/handler0alter.cc 2011-06-01 20:53:47.857807037 +0900
297+@@ -637,6 +637,7 @@
298+ ibool dict_locked = FALSE;
299+ ulint new_primary;
300+ int error;
301++ ulint should_fake_changes = FALSE;
302+
303+ DBUG_ENTER("ha_innobase::add_index");
304+ ut_a(table);
305+@@ -654,11 +655,16 @@
306+ /* In case MySQL calls this in the middle of a SELECT query, release
307+ possible adaptive hash latch to avoid deadlocks of threads. */
308+ trx_search_latch_release_if_reserved(prebuilt->trx);
309++ if (prebuilt->trx->fake_changes) {
310++ prebuilt->trx->fake_changes = FALSE;
311++ should_fake_changes = TRUE;
312++ }
313+ trx_start_if_not_started(prebuilt->trx);
314+
315+ /* Create a background transaction for the operations on
316+ the data dictionary tables. */
317+ trx = innobase_trx_allocate(user_thd);
318++ trx->fake_changes = FALSE;
319+ trx_start_if_not_started(trx);
320+
321+ innodb_table = indexed_table
322+@@ -684,6 +690,9 @@
323+ trx_general_rollback_for_mysql(trx, NULL);
324+ trx_free_for_mysql(trx);
325+ trx_commit_for_mysql(prebuilt->trx);
326++ if (should_fake_changes) {
327++ prebuilt->trx->fake_changes = TRUE;
328++ }
329+ DBUG_RETURN(error);
330+ }
331+
332+@@ -924,6 +933,9 @@
333+ trx_commit_for_mysql(trx);
334+ if (prebuilt->trx) {
335+ trx_commit_for_mysql(prebuilt->trx);
336++ if (should_fake_changes) {
337++ prebuilt->trx->fake_changes = TRUE;
338++ }
339+ }
340+
341+ if (dict_locked) {
342+@@ -1171,6 +1183,7 @@
343+ /* Create a background transaction for the operations on
344+ the data dictionary tables. */
345+ trx = innobase_trx_allocate(user_thd);
346++ trx->fake_changes = FALSE;
347+ trx_start_if_not_started(trx);
348+
349+ /* Flag this transaction as a dictionary operation, so that
350+diff -ruN a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
351+--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c 2011-06-01 20:53:21.461388361 +0900
352++++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c 2011-06-01 20:53:47.864416327 +0900
353+@@ -2613,6 +2613,8 @@
354+
355+ ut_a(trx_sys_multiple_tablespace_format);
356+
357++ ut_ad(!(thr_get_trx(thr)->fake_changes));
358++
359+ do_merge = FALSE;
360+
361+ mutex_enter(&ibuf_mutex);
362+diff -ruN a/storage/innodb_plugin/include/trx0trx.h b/storage/innodb_plugin/include/trx0trx.h
363+--- a/storage/innodb_plugin/include/trx0trx.h 2011-06-01 20:53:21.872383134 +0900
364++++ b/storage/innodb_plugin/include/trx0trx.h 2011-06-01 20:53:47.868416266 +0900
365+@@ -498,6 +498,7 @@
366+ 150 bytes in the undo log size as then
367+ we skip XA steps */
368+ ulint flush_log_at_trx_commit_session;
369++ ulint fake_changes;
370+ ulint flush_log_later;/* In 2PC, we hold the
371+ prepare_commit mutex across
372+ both phases. In that case, we
373+diff -ruN a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c
374+--- a/storage/innodb_plugin/lock/lock0lock.c 2011-06-01 20:53:22.558418930 +0900
375++++ b/storage/innodb_plugin/lock/lock0lock.c 2011-06-01 20:53:47.880418973 +0900
376+@@ -3908,6 +3908,10 @@
377+
378+ trx = thr_get_trx(thr);
379+
380++ if (trx->fake_changes && mode == LOCK_IX) {
381++ mode = LOCK_IS;
382++ }
383++
384+ lock_mutex_enter_kernel();
385+
386+ /* Look for stronger locks the same trx already has on the table */
387+@@ -5109,6 +5113,11 @@
388+ }
389+
390+ trx = thr_get_trx(thr);
391++
392++ if (trx->fake_changes) {
393++ return(DB_SUCCESS);
394++ }
395++
396+ next_rec = page_rec_get_next_const(rec);
397+ next_rec_heap_no = page_rec_get_heap_no(next_rec);
398+
399+@@ -5277,6 +5286,10 @@
400+ return(DB_SUCCESS);
401+ }
402+
403++ if (thr && thr_get_trx(thr)->fake_changes) {
404++ return(DB_SUCCESS);
405++ }
406++
407+ heap_no = rec_offs_comp(offsets)
408+ ? rec_get_heap_no_new(rec)
409+ : rec_get_heap_no_old(rec);
410+@@ -5335,6 +5348,10 @@
411+ return(DB_SUCCESS);
412+ }
413+
414++ if (thr && thr_get_trx(thr)->fake_changes) {
415++ return(DB_SUCCESS);
416++ }
417++
418+ heap_no = page_rec_get_heap_no(rec);
419+
420+ /* Another transaction cannot have an implicit lock on the record,
421+@@ -5422,6 +5439,10 @@
422+ return(DB_SUCCESS);
423+ }
424+
425++ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
426++ mode = LOCK_S;
427++ }
428++
429+ heap_no = page_rec_get_heap_no(rec);
430+
431+ lock_mutex_enter_kernel();
432+@@ -5499,6 +5520,10 @@
433+ return(DB_SUCCESS);
434+ }
435+
436++ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
437++ mode = LOCK_S;
438++ }
439++
440+ heap_no = page_rec_get_heap_no(rec);
441+
442+ lock_mutex_enter_kernel();
443+diff -ruN a/storage/innodb_plugin/que/que0que.c b/storage/innodb_plugin/que/que0que.c
444+--- a/storage/innodb_plugin/que/que0que.c 2011-06-01 20:53:21.615416412 +0900
445++++ b/storage/innodb_plugin/que/que0que.c 2011-06-01 20:53:47.883416448 +0900
446+@@ -1418,6 +1418,12 @@
447+
448+ ut_a(trx->error_state == DB_SUCCESS);
449+
450++ if (trx->fake_changes) {
451++ /* fake_changes should not access to system tables */
452++ fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
453++ return(DB_ERROR);
454++ }
455++
456+ if (reserve_dict_mutex) {
457+ mutex_enter(&dict_sys->mutex);
458+ }
459+diff -ruN a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
460+--- a/storage/innodb_plugin/row/row0ins.c 2011-06-01 20:53:22.163388220 +0900
461++++ b/storage/innodb_plugin/row/row0ins.c 2011-06-01 20:53:47.887385509 +0900
462+@@ -1512,6 +1512,11 @@
463+ if (UNIV_LIKELY_NULL(heap)) {
464+ mem_heap_free(heap);
465+ }
466++
467++ if (trx->fake_changes) {
468++ err = DB_SUCCESS;
469++ }
470++
471+ return(err);
472+ }
473+
474+@@ -2013,7 +2018,7 @@
475+ }
476+
477+ btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
478+- mode | BTR_INSERT | ignore_sec_unique,
479++ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT | ignore_sec_unique),
480+ &cursor, 0, __FILE__, __LINE__, &mtr);
481+
482+ if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
483+@@ -2073,7 +2078,7 @@
484+
485+ btr_cur_search_to_nth_level(index, 0, entry,
486+ PAGE_CUR_LE,
487+- mode | BTR_INSERT,
488++ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
489+ &cursor, 0,
490+ __FILE__, __LINE__, &mtr);
491+ }
492+@@ -2127,6 +2132,22 @@
493+ if (UNIV_LIKELY_NULL(big_rec)) {
494+ rec_t* rec;
495+ ulint* offsets;
496++
497++ if (thr_get_trx(thr)->fake_changes) {
498++ /* skip store extern */
499++ if (modify) {
500++ dtuple_big_rec_free(big_rec);
501++ } else {
502++ dtuple_convert_back_big_rec(index, entry, big_rec);
503++ }
504++
505++ if (UNIV_LIKELY_NULL(heap)) {
506++ mem_heap_free(heap);
507++ }
508++
509++ return(err);
510++ }
511++
512+ mtr_start(&mtr);
513+
514+ btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
515+diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
516+--- a/storage/innodb_plugin/row/row0mysql.c 2011-06-01 20:53:22.400536598 +0900
517++++ b/storage/innodb_plugin/row/row0mysql.c 2011-06-01 20:53:47.894468387 +0900
518+@@ -1189,6 +1189,7 @@
519+ prebuilt->table->stat_n_rows--;
520+ }
521+
522++ if (!(trx->fake_changes))
523+ row_update_statistics_if_needed(prebuilt->table);
524+ trx->op_info = "";
525+
526+@@ -1449,6 +1450,7 @@
527+ that changes indexed columns, UPDATEs that change only non-indexed
528+ columns would not affect statistics. */
529+ if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
530++ if (!(trx->fake_changes))
531+ row_update_statistics_if_needed(prebuilt->table);
532+ }
533+
534+@@ -1667,6 +1669,7 @@
535+ srv_n_rows_updated++;
536+ }
537+
538++ if (!(trx->fake_changes))
539+ row_update_statistics_if_needed(table);
540+
541+ return(err);
542+diff -ruN a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
543+--- a/storage/innodb_plugin/row/row0upd.c 2011-06-01 20:53:21.653387273 +0900
544++++ b/storage/innodb_plugin/row/row0upd.c 2011-06-01 20:53:47.901499571 +0900
545+@@ -1591,8 +1591,9 @@
546+
547+ mtr_start(&mtr);
548+
549+- found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
550+- &mtr);
551++ found = row_search_index_entry(index, entry,
552++ trx->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
553++ &pcur, &mtr);
554+ btr_cur = btr_pcur_get_btr_cur(&pcur);
555+
556+ rec = btr_cur_get_rec(btr_cur);
557+@@ -1822,9 +1823,11 @@
558+ the previous invocation of this function. Mark the
559+ off-page columns in the entry inherited. */
560+
561++ if (!(trx->fake_changes)) {
562+ change_ownership = row_upd_clust_rec_by_insert_inherit(
563+ NULL, NULL, entry, node->update);
564+ ut_a(change_ownership);
565++ }
566+ /* fall through */
567+ case UPD_NODE_INSERT_CLUSTERED:
568+ /* A lock wait occurred in row_ins_index_entry() in
569+@@ -1854,7 +1857,7 @@
570+ delete-marked old record, mark them disowned by the
571+ old record and owned by the new entry. */
572+
573+- if (rec_offs_any_extern(offsets)) {
574++ if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
575+ change_ownership = row_upd_clust_rec_by_insert_inherit(
576+ rec, offsets, entry, node->update);
577+
578+@@ -1982,7 +1985,8 @@
579+ the same transaction do not modify the record in the meantime.
580+ Therefore we can assert that the restoration of the cursor succeeds. */
581+
582+- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
583++ ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
584++ pcur, mtr));
585+
586+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
587+ dict_table_is_comp(index->table)));
588+@@ -1992,7 +1996,8 @@
589+ node->cmpl_info, thr, mtr);
590+ mtr_commit(mtr);
591+
592+- if (err == DB_SUCCESS && big_rec) {
593++ /* skip store extern for fake_changes */
594++ if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
595+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
596+ rec_t* rec;
597+ rec_offs_init(offsets_);
598+@@ -2117,7 +2122,8 @@
599+
600+ ut_a(pcur->rel_pos == BTR_PCUR_ON);
601+
602+- success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
603++ success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
604++ pcur, mtr);
605+
606+ if (!success) {
607+ err = DB_RECORD_NOT_FOUND;
608+diff -ruN a/storage/innodb_plugin/trx/trx0trx.c b/storage/innodb_plugin/trx/trx0trx.c
609+--- a/storage/innodb_plugin/trx/trx0trx.c 2011-06-01 20:53:21.901372073 +0900
610++++ b/storage/innodb_plugin/trx/trx0trx.c 2011-06-01 20:53:47.907481601 +0900
611+@@ -111,6 +111,8 @@
612+
613+ trx->flush_log_at_trx_commit_session = 3; /* means to use innodb_flush_log_at_trx_commit value */
614+
615++ trx->fake_changes = FALSE;
616++
617+ trx->check_foreigns = TRUE;
618+ trx->check_unique_secondary = TRUE;
619+
620
621=== modified file 'series'
622--- series 2011-04-20 07:13:25 +0000
623+++ series 2011-06-01 12:17:31 +0000
624@@ -44,6 +44,7 @@
625 log_connection_error.patch
626 mysql-syslog.patch
627 innodb_buffer_pool_shm.patch
628+innodb_fake_changes.patch
629 response-time-distribution.patch
630 error_pad.patch
631 remove_fcntl_excessive_calls.patch

Subscribers

People subscribed via source and target branches