Merge lp:~percona-dev/percona-server/5.1.57-innodb_fake_changes into lp:~percona-dev/percona-server/5.1.57
- 5.1.57-innodb_fake_changes
- Merge into 5.1.57
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vadim Tkachenko | Abstain | ||
Stewart Smith | Pending | ||
Review via email: mp+63106@code.launchpad.net |
Commit message
Description of the change
- new boolean session variable 'innodb_
- 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
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.
Stewart Smith (stewart) wrote : | # |
marking as merged as we have merged the feature into lp:percona-server/5.1
Preview Diff
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 |
I assign it to stewart, the feature should have test and documentation