Merge lp:~akopytov/percona-server/bug1131189-5.6 into lp:percona-server/5.6
- bug1131189-5.6
- Merge into 5.6
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Laurynas Biveinis | ||||||||||||
Approved revision: | no longer in the source branch. | ||||||||||||
Merged at revision: | 356 | ||||||||||||
Proposed branch: | lp:~akopytov/percona-server/bug1131189-5.6 | ||||||||||||
Merge into: | lp:percona-server/5.6 | ||||||||||||
Prerequisite: | lp:~laurynas-biveinis/percona-server/ci-fixes-5.6.11 | ||||||||||||
Diff against target: |
1545 lines (+617/-233) 21 files modified
Percona-Server/sql/handler.cc (+7/-17) Percona-Server/sql/sql_base.cc (+9/-3) Percona-Server/sql/sql_class.cc (+1/-3) Percona-Server/sql/sql_connect.cc (+9/-6) Percona-Server/sql/sql_parse.cc (+6/-2) Percona-Server/sql/sql_prepare.cc (+26/-10) Percona-Server/storage/innobase/include/read0read.h (+7/-4) Percona-Server/storage/innobase/include/read0read.ic (+11/-28) Percona-Server/storage/innobase/include/trx0sys.h (+58/-10) Percona-Server/storage/innobase/include/trx0sys.ic (+66/-13) Percona-Server/storage/innobase/include/trx0trx.h (+24/-0) Percona-Server/storage/innobase/lock/lock0lock.cc (+13/-3) Percona-Server/storage/innobase/read/read0read.cc (+82/-114) Percona-Server/storage/innobase/row/row0sel.cc (+2/-2) Percona-Server/storage/innobase/row/row0vers.cc (+5/-8) Percona-Server/storage/innobase/trx/trx0sys.cc (+10/-0) Percona-Server/storage/innobase/trx/trx0trx.cc (+177/-10) policy/apparmor/usr.sbin.mysqld (+61/-0) policy/apparmor/usr.sbin.mysqld.local (+2/-0) policy/selinux/percona-server.fc (+6/-0) policy/selinux/percona-server.te (+35/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~akopytov/percona-server/bug1131189-5.6 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+165584@code.launchpad.net |
Description of the change
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Will merge as-is and handle the minor issues in a follow-up.
Alexey Kopytov (akopytov) wrote : | # |
Hi Laurynas,
On Fri, 24 May 2013 14:22:31 -0000, Laurynas Biveinis wrote:
> Review: Needs Fixing
>
> - The patch would be OK, but I did find one issue which IMHO
> requires recommitting (although the test cycle could be
> skipped) or follow-up addressing (I don't have a strong opinion
> on recomitting vs follow-up): trx_rw_
> bool-returning function that returns NULL in one of the code
> paths.
Right, good catch! Thanks for fixing it as a followup.
>
> - If we are recommitting, then in_trx_serial_list should be bool,
> not ibool as well, and true/false used instead of 0/1 for
> setting it, spurious newline at diff line 278. The row0sel.cc
> change is spurious as well?
>
I deliberately made it ibool to be consistent with in_ro_trx_list /
in_rw_trx_list (which is also new 5.6 code BTW). But OK.
> Random remark:
>
> - trx_descr_cmp() should be defined in trx0trx.ic, not .c? So
> then compiler can resolve the function pointer to inlining. It
> is also possible to use std::binary_
> C++ world.
>
bsearch() is a library function, so no inlining is possible. Is it
different with std::binary_
> Last and least absolutely random remarks:
>
> - I don't fully understand the header comment for
> trx_rw_
> must not be dereferenced unless lock_sys->mutex is held. But
> the function itself dereferences the pointer in
> trx_state_eq()? I see that all callers hold the
> lock_sys->mutex, thus it does not seem to be a real issue
> though.
>
There's actually an upstream problem with that code, but it only applies
to debug builds. Will report it separately.
> - Upstream started making heavy use of __attribute__ function
> annotations to cause extra warnings on misuse, especially
> nonnull, warn_unused_result. Maybe not bad idea for us well
> where it applies.
>
Yes, that's good stuff.
/Alexey
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Ah, indeed trx_descr_cmp() is just a wrapper around bsearch(), thus removing the indirection would not help there.
std::binary_
Preview Diff
1 | === modified file 'Percona-Server/sql/handler.cc' | |||
2 | --- Percona-Server/sql/handler.cc 2013-05-12 06:24:46 +0000 | |||
3 | +++ Percona-Server/sql/handler.cc 2013-05-24 12:02:59 +0000 | |||
4 | @@ -2516,8 +2516,13 @@ | |||
5 | 2516 | dup_ref=ref+ALIGN_SIZE(ref_length); | 2516 | dup_ref=ref+ALIGN_SIZE(ref_length); |
6 | 2517 | cached_table_flags= table_flags(); | 2517 | cached_table_flags= table_flags(); |
7 | 2518 | } | 2518 | } |
10 | 2519 | rows_read= rows_changed= 0; | 2519 | |
11 | 2520 | memset(index_rows_read, 0, sizeof(index_rows_read)); | 2520 | if (unlikely(opt_userstat)) |
12 | 2521 | { | ||
13 | 2522 | rows_read= rows_changed= 0; | ||
14 | 2523 | memset(index_rows_read, 0, sizeof(index_rows_read)); | ||
15 | 2524 | } | ||
16 | 2525 | |||
17 | 2521 | DBUG_RETURN(error); | 2526 | DBUG_RETURN(error); |
18 | 2522 | } | 2527 | } |
19 | 2523 | 2528 | ||
20 | @@ -4667,12 +4672,6 @@ | |||
21 | 4667 | // Updates the global table stats with the TABLE this handler represents. | 4672 | // Updates the global table stats with the TABLE this handler represents. |
22 | 4668 | void handler::update_global_table_stats() | 4673 | void handler::update_global_table_stats() |
23 | 4669 | { | 4674 | { |
24 | 4670 | if (!opt_userstat) | ||
25 | 4671 | { | ||
26 | 4672 | rows_read= rows_changed= 0; | ||
27 | 4673 | return; | ||
28 | 4674 | } | ||
29 | 4675 | |||
30 | 4676 | if (!rows_read && !rows_changed) | 4675 | if (!rows_read && !rows_changed) |
31 | 4677 | return; // Nothing to update. | 4676 | return; // Nothing to update. |
32 | 4678 | // table_cache_key is db_name + '\0' + table_name + '\0'. | 4677 | // table_cache_key is db_name + '\0' + table_name + '\0'. |
33 | @@ -4730,15 +4729,6 @@ | |||
34 | 4730 | !table->s->table_name.str) | 4729 | !table->s->table_name.str) |
35 | 4731 | return; | 4730 | return; |
36 | 4732 | 4731 | ||
37 | 4733 | if (!opt_userstat) | ||
38 | 4734 | { | ||
39 | 4735 | for (uint x= 0; x < table->s->keys; ++x) | ||
40 | 4736 | { | ||
41 | 4737 | index_rows_read[x]= 0; | ||
42 | 4738 | } | ||
43 | 4739 | return; | ||
44 | 4740 | } | ||
45 | 4741 | |||
46 | 4742 | for (uint x = 0; x < table->s->keys; ++x) | 4732 | for (uint x = 0; x < table->s->keys; ++x) |
47 | 4743 | { | 4733 | { |
48 | 4744 | if (index_rows_read[x]) | 4734 | if (index_rows_read[x]) |
49 | 4745 | 4735 | ||
50 | === modified file 'Percona-Server/sql/sql_base.cc' | |||
51 | --- Percona-Server/sql/sql_base.cc 2013-05-13 04:25:56 +0000 | |||
52 | +++ Percona-Server/sql/sql_base.cc 2013-05-24 12:02:59 +0000 | |||
53 | @@ -1490,11 +1490,13 @@ | |||
54 | 1490 | table->mdl_ticket= NULL; | 1490 | table->mdl_ticket= NULL; |
55 | 1491 | 1491 | ||
56 | 1492 | mysql_mutex_lock(&thd->LOCK_thd_data); | 1492 | mysql_mutex_lock(&thd->LOCK_thd_data); |
58 | 1493 | if(table->file) | 1493 | |
59 | 1494 | if(unlikely(opt_userstat && table->file)) | ||
60 | 1494 | { | 1495 | { |
61 | 1495 | table->file->update_global_table_stats(); | 1496 | table->file->update_global_table_stats(); |
62 | 1496 | table->file->update_global_index_stats(); | 1497 | table->file->update_global_index_stats(); |
63 | 1497 | } | 1498 | } |
64 | 1499 | |||
65 | 1498 | *table_ptr=table->next; | 1500 | *table_ptr=table->next; |
66 | 1499 | mysql_mutex_unlock(&thd->LOCK_thd_data); | 1501 | mysql_mutex_unlock(&thd->LOCK_thd_data); |
67 | 1500 | 1502 | ||
68 | @@ -2152,8 +2154,12 @@ | |||
69 | 2152 | DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", | 2154 | DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", |
70 | 2153 | table->s->db.str, table->s->table_name.str)); | 2155 | table->s->db.str, table->s->table_name.str)); |
71 | 2154 | 2156 | ||
74 | 2155 | table->file->update_global_table_stats(); | 2157 | if (unlikely(opt_userstat)) |
75 | 2156 | table->file->update_global_index_stats(); | 2158 | { |
76 | 2159 | table->file->update_global_table_stats(); | ||
77 | 2160 | table->file->update_global_index_stats(); | ||
78 | 2161 | } | ||
79 | 2162 | |||
80 | 2157 | free_io_cache(table); | 2163 | free_io_cache(table); |
81 | 2158 | closefrm(table, 0); | 2164 | closefrm(table, 0); |
82 | 2159 | if (delete_table) | 2165 | if (delete_table) |
83 | 2160 | 2166 | ||
84 | === modified file 'Percona-Server/sql/sql_class.cc' | |||
85 | --- Percona-Server/sql/sql_class.cc 2013-05-22 10:51:07 +0000 | |||
86 | +++ Percona-Server/sql/sql_class.cc 2013-05-24 12:02:59 +0000 | |||
87 | @@ -1520,8 +1520,6 @@ | |||
88 | 1520 | // Updates 'diff' stats of a THD. | 1520 | // Updates 'diff' stats of a THD. |
89 | 1521 | void THD::update_stats(bool ran_command) | 1521 | void THD::update_stats(bool ran_command) |
90 | 1522 | { | 1522 | { |
91 | 1523 | if (opt_userstat) | ||
92 | 1524 | { | ||
93 | 1525 | diff_total_busy_time+= busy_time; | 1523 | diff_total_busy_time+= busy_time; |
94 | 1526 | diff_total_cpu_time+= cpu_time; | 1524 | diff_total_cpu_time+= cpu_time; |
95 | 1527 | diff_total_bytes_received+= bytes_received; | 1525 | diff_total_bytes_received+= bytes_received; |
96 | @@ -1566,7 +1564,7 @@ | |||
97 | 1566 | /* reset counters to zero to avoid double-counting since values | 1564 | /* reset counters to zero to avoid double-counting since values |
98 | 1567 | are already store in diff_total_*. | 1565 | are already store in diff_total_*. |
99 | 1568 | */ | 1566 | */ |
101 | 1569 | } | 1567 | |
102 | 1570 | busy_time= 0; | 1568 | busy_time= 0; |
103 | 1571 | cpu_time= 0; | 1569 | cpu_time= 0; |
104 | 1572 | bytes_received= 0; | 1570 | bytes_received= 0; |
105 | 1573 | 1571 | ||
106 | === modified file 'Percona-Server/sql/sql_connect.cc' | |||
107 | --- Percona-Server/sql/sql_connect.cc 2013-05-22 10:51:07 +0000 | |||
108 | +++ Percona-Server/sql/sql_connect.cc 2013-05-24 12:02:59 +0000 | |||
109 | @@ -566,9 +566,6 @@ | |||
110 | 566 | const char* client_string= get_client_host(thd); | 566 | const char* client_string= get_client_host(thd); |
111 | 567 | int return_value= 0; | 567 | int return_value= 0; |
112 | 568 | 568 | ||
113 | 569 | if (!opt_userstat) | ||
114 | 570 | return return_value; | ||
115 | 571 | |||
116 | 572 | if (acl_is_utility_user(thd->security_ctx->user, thd->security_ctx->host, | 569 | if (acl_is_utility_user(thd->security_ctx->user, thd->security_ctx->host, |
117 | 573 | thd->security_ctx->ip)) | 570 | thd->security_ctx->ip)) |
118 | 574 | return return_value; | 571 | return return_value; |
119 | @@ -1383,8 +1380,9 @@ | |||
120 | 1383 | my_net_set_write_timeout(net, thd->variables.net_write_timeout); | 1380 | my_net_set_write_timeout(net, thd->variables.net_write_timeout); |
121 | 1384 | 1381 | ||
122 | 1385 | thd->reset_stats(); | 1382 | thd->reset_stats(); |
123 | 1383 | |||
124 | 1386 | // Updates global user connection stats. | 1384 | // Updates global user connection stats. |
126 | 1387 | if (increment_connection_count(thd, true)) | 1385 | if (opt_userstat && increment_connection_count(thd, true)) |
127 | 1388 | DBUG_RETURN(1); | 1386 | DBUG_RETURN(1); |
128 | 1389 | 1387 | ||
129 | 1390 | DBUG_RETURN(0); | 1388 | DBUG_RETURN(0); |
130 | @@ -1621,8 +1619,13 @@ | |||
131 | 1621 | 1619 | ||
132 | 1622 | end_thread: | 1620 | end_thread: |
133 | 1623 | close_connection(thd); | 1621 | close_connection(thd); |
136 | 1624 | thd->update_stats(false); | 1622 | |
137 | 1625 | update_global_user_stats(thd, create_user, time(NULL)); | 1623 | if (unlikely(opt_userstat)) |
138 | 1624 | { | ||
139 | 1625 | thd->update_stats(false); | ||
140 | 1626 | update_global_user_stats(thd, create_user, time(NULL)); | ||
141 | 1627 | } | ||
142 | 1628 | |||
143 | 1626 | if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) | 1629 | if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) |
144 | 1627 | return; // Probably no-threads | 1630 | return; // Probably no-threads |
145 | 1628 | 1631 | ||
146 | 1629 | 1632 | ||
147 | === modified file 'Percona-Server/sql/sql_parse.cc' | |||
148 | --- Percona-Server/sql/sql_parse.cc 2013-05-22 10:51:07 +0000 | |||
149 | +++ Percona-Server/sql/sql_parse.cc 2013-05-24 12:02:59 +0000 | |||
150 | @@ -6545,11 +6545,15 @@ | |||
151 | 6545 | else | 6545 | else |
152 | 6546 | thd->cpu_time = 0; | 6546 | thd->cpu_time = 0; |
153 | 6547 | } | 6547 | } |
154 | 6548 | |||
155 | 6548 | // Updates THD stats and the global user stats. | 6549 | // Updates THD stats and the global user stats. |
157 | 6549 | thd->update_stats(true); | 6550 | if (unlikely(opt_userstat)) |
158 | 6551 | { | ||
159 | 6552 | thd->update_stats(true); | ||
160 | 6550 | #ifndef EMBEDDED_LIBRARY | 6553 | #ifndef EMBEDDED_LIBRARY |
162 | 6551 | update_global_user_stats(thd, true, time(NULL)); | 6554 | update_global_user_stats(thd, true, time(NULL)); |
163 | 6552 | #endif | 6555 | #endif |
164 | 6556 | } | ||
165 | 6553 | 6557 | ||
166 | 6554 | DBUG_VOID_RETURN; | 6558 | DBUG_VOID_RETURN; |
167 | 6555 | } | 6559 | } |
168 | 6556 | 6560 | ||
169 | === modified file 'Percona-Server/sql/sql_prepare.cc' | |||
170 | --- Percona-Server/sql/sql_prepare.cc 2013-05-12 06:24:46 +0000 | |||
171 | +++ Percona-Server/sql/sql_prepare.cc 2013-05-24 12:02:59 +0000 | |||
172 | @@ -2267,7 +2267,7 @@ | |||
173 | 2267 | double start_cpu_nsecs= 0; | 2267 | double start_cpu_nsecs= 0; |
174 | 2268 | double end_cpu_nsecs= 0; | 2268 | double end_cpu_nsecs= 0; |
175 | 2269 | 2269 | ||
177 | 2270 | if (opt_userstat) | 2270 | if (unlikely(opt_userstat)) |
178 | 2271 | { | 2271 | { |
179 | 2272 | #ifdef HAVE_CLOCK_GETTIME | 2272 | #ifdef HAVE_CLOCK_GETTIME |
180 | 2273 | /* get start cputime */ | 2273 | /* get start cputime */ |
181 | @@ -2309,7 +2309,7 @@ | |||
182 | 2309 | 2309 | ||
183 | 2310 | /* check_prepared_statemnt sends the metadata packet in case of success */ | 2310 | /* check_prepared_statemnt sends the metadata packet in case of success */ |
184 | 2311 | end: | 2311 | end: |
186 | 2312 | if (opt_userstat) | 2312 | if (unlikely(opt_userstat)) |
187 | 2313 | { | 2313 | { |
188 | 2314 | // Gets the end time. | 2314 | // Gets the end time. |
189 | 2315 | if (!(end_time_error= gettimeofday(&end_time, NULL))) | 2315 | if (!(end_time_error= gettimeofday(&end_time, NULL))) |
190 | @@ -2351,11 +2351,15 @@ | |||
191 | 2351 | else | 2351 | else |
192 | 2352 | thd->cpu_time = 0; | 2352 | thd->cpu_time = 0; |
193 | 2353 | } | 2353 | } |
194 | 2354 | |||
195 | 2354 | // Updates THD stats and the global user stats. | 2355 | // Updates THD stats and the global user stats. |
197 | 2355 | thd->update_stats(true); | 2356 | if (unlikely(opt_userstat)) |
198 | 2357 | { | ||
199 | 2358 | thd->update_stats(true); | ||
200 | 2356 | #ifndef EMBEDDED_LIBRARY | 2359 | #ifndef EMBEDDED_LIBRARY |
202 | 2357 | update_global_user_stats(thd, true, time(NULL)); | 2360 | update_global_user_stats(thd, true, time(NULL)); |
203 | 2358 | #endif | 2361 | #endif |
204 | 2362 | } | ||
205 | 2359 | 2363 | ||
206 | 2360 | DBUG_VOID_RETURN; | 2364 | DBUG_VOID_RETURN; |
207 | 2361 | } | 2365 | } |
208 | @@ -2813,11 +2817,15 @@ | |||
209 | 2813 | else | 2817 | else |
210 | 2814 | thd->cpu_time = 0; | 2818 | thd->cpu_time = 0; |
211 | 2815 | } | 2819 | } |
212 | 2820 | |||
213 | 2816 | // Updates THD stats and the global user stats. | 2821 | // Updates THD stats and the global user stats. |
215 | 2817 | thd->update_stats(true); | 2822 | if (unlikely(opt_userstat)) |
216 | 2823 | { | ||
217 | 2824 | thd->update_stats(true); | ||
218 | 2818 | #ifndef EMBEDDED_LIBRARY | 2825 | #ifndef EMBEDDED_LIBRARY |
220 | 2819 | update_global_user_stats(thd, true, time(NULL)); | 2826 | update_global_user_stats(thd, true, time(NULL)); |
221 | 2820 | #endif | 2827 | #endif |
222 | 2828 | } | ||
223 | 2821 | 2829 | ||
224 | 2822 | DBUG_VOID_RETURN; | 2830 | DBUG_VOID_RETURN; |
225 | 2823 | } | 2831 | } |
226 | @@ -2990,11 +2998,15 @@ | |||
227 | 2990 | } else | 2998 | } else |
228 | 2991 | thd->cpu_time= 0; | 2999 | thd->cpu_time= 0; |
229 | 2992 | } | 3000 | } |
230 | 3001 | |||
231 | 2993 | // Updates THD stats and the global user stats. | 3002 | // Updates THD stats and the global user stats. |
233 | 2994 | thd->update_stats(true); | 3003 | if (unlikely(opt_userstat)) |
234 | 3004 | { | ||
235 | 3005 | thd->update_stats(true); | ||
236 | 2995 | #ifndef EMBEDDED_LIBRARY | 3006 | #ifndef EMBEDDED_LIBRARY |
238 | 2996 | update_global_user_stats(thd, true, time(NULL)); | 3007 | update_global_user_stats(thd, true, time(NULL)); |
239 | 2997 | #endif | 3008 | #endif |
240 | 3009 | } | ||
241 | 2998 | 3010 | ||
242 | 2999 | DBUG_VOID_RETURN; | 3011 | DBUG_VOID_RETURN; |
243 | 3000 | } | 3012 | } |
244 | @@ -3118,11 +3130,15 @@ | |||
245 | 3118 | else | 3130 | else |
246 | 3119 | thd->cpu_time= 0; | 3131 | thd->cpu_time= 0; |
247 | 3120 | } | 3132 | } |
248 | 3133 | |||
249 | 3121 | // Updates THD stats and the global user stats. | 3134 | // Updates THD stats and the global user stats. |
251 | 3122 | thd->update_stats(true); | 3135 | if (unlikely(opt_userstat)) |
252 | 3136 | { | ||
253 | 3137 | thd->update_stats(true); | ||
254 | 3123 | #ifndef EMBEDDED_LIBRARY | 3138 | #ifndef EMBEDDED_LIBRARY |
256 | 3124 | update_global_user_stats(thd, true, time(NULL)); | 3139 | update_global_user_stats(thd, true, time(NULL)); |
257 | 3125 | #endif | 3140 | #endif |
258 | 3141 | } | ||
259 | 3126 | 3142 | ||
260 | 3127 | DBUG_VOID_RETURN; | 3143 | DBUG_VOID_RETURN; |
261 | 3128 | } | 3144 | } |
262 | 3129 | 3145 | ||
263 | === modified file 'Percona-Server/storage/innobase/include/read0read.h' | |||
264 | --- Percona-Server/storage/innobase/include/read0read.h 2013-05-23 06:51:50 +0000 | |||
265 | +++ Percona-Server/storage/innobase/include/read0read.h 2013-05-24 12:02:59 +0000 | |||
266 | @@ -32,6 +32,7 @@ | |||
267 | 32 | #include "ut0byte.h" | 32 | #include "ut0byte.h" |
268 | 33 | #include "ut0lst.h" | 33 | #include "ut0lst.h" |
269 | 34 | #include "trx0trx.h" | 34 | #include "trx0trx.h" |
270 | 35 | #include "trx0sys.h" | ||
271 | 35 | #include "read0types.h" | 36 | #include "read0types.h" |
272 | 36 | 37 | ||
273 | 37 | /*********************************************************************//** | 38 | /*********************************************************************//** |
274 | @@ -46,6 +47,7 @@ | |||
275 | 46 | transaction, or 0 used in purge */ | 47 | transaction, or 0 used in purge */ |
276 | 47 | read_view_t*& view); /*!< in,out: pre-allocated view array or | 48 | read_view_t*& view); /*!< in,out: pre-allocated view array or |
277 | 48 | NULL if a new one needs to be created */ | 49 | NULL if a new one needs to be created */ |
278 | 50 | |||
279 | 49 | /*********************************************************************//** | 51 | /*********************************************************************//** |
280 | 50 | Makes a copy of the oldest existing read view, or opens a new. The view | 52 | Makes a copy of the oldest existing read view, or opens a new. The view |
281 | 51 | must be closed with ..._close. | 53 | must be closed with ..._close. |
282 | @@ -154,17 +156,18 @@ | |||
283 | 154 | are strictly smaller (<) than this value. | 156 | are strictly smaller (<) than this value. |
284 | 155 | In other words, | 157 | In other words, |
285 | 156 | this is the "low water mark". */ | 158 | this is the "low water mark". */ |
287 | 157 | ulint n_trx_ids; | 159 | ulint n_descr; |
288 | 158 | /*!< Number of cells in the trx_ids array */ | 160 | /*!< Number of cells in the trx_ids array */ |
290 | 159 | ulint max_trx_ids; | 161 | ulint max_descr; |
291 | 160 | /*!< Maximum number of cells in the trx_ids | 162 | /*!< Maximum number of cells in the trx_ids |
292 | 161 | array */ | 163 | array */ |
294 | 162 | trx_id_t* trx_ids;/*!< Additional trx ids which the read should | 164 | trx_id_t* descriptors; |
295 | 165 | /*!< Additional trx ids which the read should | ||
296 | 163 | not see: typically, these are the read-write | 166 | not see: typically, these are the read-write |
297 | 164 | active transactions at the time when the read | 167 | active transactions at the time when the read |
298 | 165 | is serialized, except the reading transaction | 168 | is serialized, except the reading transaction |
299 | 166 | itself; the trx ids in this array are in a | 169 | itself; the trx ids in this array are in a |
301 | 167 | descending order. These trx_ids should be | 170 | ascending order. These trx_ids should be |
302 | 168 | between the "low" and "high" water marks, | 171 | between the "low" and "high" water marks, |
303 | 169 | that is, up_limit_id and low_limit_id. */ | 172 | that is, up_limit_id and low_limit_id. */ |
304 | 170 | trx_id_t creator_trx_id; | 173 | trx_id_t creator_trx_id; |
305 | 171 | 174 | ||
306 | === modified file 'Percona-Server/storage/innobase/include/read0read.ic' | |||
307 | --- Percona-Server/storage/innobase/include/read0read.ic 2012-08-22 01:40:20 +0000 | |||
308 | +++ Percona-Server/storage/innobase/include/read0read.ic 2013-05-24 12:02:59 +0000 | |||
309 | @@ -35,11 +35,13 @@ | |||
310 | 35 | const read_view_t* view) /*!< in: view to validate */ | 35 | const read_view_t* view) /*!< in: view to validate */ |
311 | 36 | { | 36 | { |
312 | 37 | ut_ad(mutex_own(&trx_sys->mutex)); | 37 | ut_ad(mutex_own(&trx_sys->mutex)); |
318 | 38 | 38 | ut_ad(view->max_descr >= view->n_descr); | |
319 | 39 | /* Check that the view->trx_ids array is in descending order. */ | 39 | ut_ad(view->descriptors == NULL || view->max_descr > 0); |
320 | 40 | for (ulint i = 1; i < view->n_trx_ids; ++i) { | 40 | |
321 | 41 | 41 | /* Check that the view->descriptors array is in ascending order. */ | |
322 | 42 | ut_a(view->trx_ids[i] < view->trx_ids[i - 1]); | 42 | for (ulint i = 1; i < view->n_descr; ++i) { |
323 | 43 | |||
324 | 44 | ut_a(view->descriptors[i] > view->descriptors[i - 1]); | ||
325 | 43 | } | 45 | } |
326 | 44 | 46 | ||
327 | 45 | return(true); | 47 | return(true); |
328 | @@ -92,31 +94,12 @@ | |||
329 | 92 | } else if (trx_id >= view->low_limit_id) { | 94 | } else if (trx_id >= view->low_limit_id) { |
330 | 93 | 95 | ||
331 | 94 | return(false); | 96 | return(false); |
332 | 95 | } else { | ||
333 | 96 | ulint lower = 0; | ||
334 | 97 | ulint upper = view->n_trx_ids - 1; | ||
335 | 98 | |||
336 | 99 | ut_a(view->n_trx_ids > 0); | ||
337 | 100 | |||
338 | 101 | do { | ||
339 | 102 | ulint mid = (lower + upper) >> 1; | ||
340 | 103 | trx_id_t mid_id = view->trx_ids[mid]; | ||
341 | 104 | |||
342 | 105 | if (mid_id == trx_id) { | ||
343 | 106 | return(FALSE); | ||
344 | 107 | } else if (mid_id < trx_id) { | ||
345 | 108 | if (mid > 0) { | ||
346 | 109 | upper = mid - 1; | ||
347 | 110 | } else { | ||
348 | 111 | break; | ||
349 | 112 | } | ||
350 | 113 | } else { | ||
351 | 114 | lower = mid + 1; | ||
352 | 115 | } | ||
353 | 116 | } while (lower <= upper); | ||
354 | 117 | } | 97 | } |
355 | 118 | 98 | ||
357 | 119 | return(true); | 99 | /* Do a binary search over this view's descriptors array */ |
358 | 100 | |||
359 | 101 | return(trx_find_descriptor(view->descriptors, view->n_descr, | ||
360 | 102 | trx_id) == NULL); | ||
361 | 120 | } | 103 | } |
362 | 121 | 104 | ||
363 | 122 | /*********************************************************************//** | 105 | /*********************************************************************//** |
364 | 123 | 106 | ||
365 | === modified file 'Percona-Server/storage/innobase/include/trx0sys.h' | |||
366 | --- Percona-Server/storage/innobase/include/trx0sys.h 2013-05-10 09:39:17 +0000 | |||
367 | +++ Percona-Server/storage/innobase/include/trx0sys.h 2013-05-24 12:02:59 +0000 | |||
368 | @@ -184,6 +184,17 @@ | |||
369 | 184 | trx_sys_get_max_trx_id(void); | 184 | trx_sys_get_max_trx_id(void); |
370 | 185 | /*========================*/ | 185 | /*========================*/ |
371 | 186 | 186 | ||
372 | 187 | /*************************************************************//** | ||
373 | 188 | Find a slot for a given trx ID in a descriptors array. | ||
374 | 189 | @return: slot pointer */ | ||
375 | 190 | UNIV_INLINE | ||
376 | 191 | trx_id_t* | ||
377 | 192 | trx_find_descriptor( | ||
378 | 193 | /*================*/ | ||
379 | 194 | const trx_id_t* descriptors, /*!< in: descriptors array */ | ||
380 | 195 | ulint n_descr, /*!< in: array size */ | ||
381 | 196 | trx_id_t trx_id); /*!< in: trx pointer */ | ||
382 | 197 | |||
383 | 187 | #ifdef UNIV_DEBUG | 198 | #ifdef UNIV_DEBUG |
384 | 188 | /* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ | 199 | /* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ |
385 | 189 | extern uint trx_rseg_n_slots_debug; | 200 | extern uint trx_rseg_n_slots_debug; |
386 | @@ -231,14 +242,26 @@ | |||
387 | 231 | trx_rw_min_trx_id(void); | 242 | trx_rw_min_trx_id(void); |
388 | 232 | /*===================*/ | 243 | /*===================*/ |
389 | 233 | /****************************************************************//** | 244 | /****************************************************************//** |
390 | 245 | Returns pointer to a transaction instance if a rw transaction with the given id | ||
391 | 246 | is active. Caller must hold trx_sys->mutex. If the caller is not holding | ||
392 | 247 | lock_sys->mutex, the transaction may already have been committed. | ||
393 | 248 | @return transaction instance if active, or NULL; | ||
394 | 249 | the pointer must not be dereferenced unless lock_sys->mutex was | ||
395 | 250 | acquired before calling this function and is still being held */ | ||
396 | 251 | UNIV_INLINE | ||
397 | 252 | trx_t* | ||
398 | 253 | trx_rw_get_active_trx_by_id( | ||
399 | 254 | /*========================*/ | ||
400 | 255 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | ||
401 | 256 | ibool* corrupt); /*!< in: NULL or pointer to a flag | ||
402 | 257 | that will be set if corrupt */ | ||
403 | 258 | /****************************************************************//** | ||
404 | 234 | Checks if a rw transaction with the given id is active. Caller must hold | 259 | Checks if a rw transaction with the given id is active. Caller must hold |
410 | 235 | trx_sys->mutex in shared mode. If the caller is not holding | 260 | trx_sys->mutex. If the caller is not holding lock_sys->mutex, the |
411 | 236 | lock_sys->mutex, the transaction may already have been committed. | 261 | transaction may already have been committed. |
412 | 237 | @return transaction instance if active, or NULL; | 262 | @return true if rw transaction it with a given id is active. */ |
408 | 238 | the pointer must not be dereferenced unless lock_sys->mutex was | ||
409 | 239 | acquired before calling this function and is still being held */ | ||
413 | 240 | UNIV_INLINE | 263 | UNIV_INLINE |
415 | 241 | trx_t* | 264 | bool |
416 | 242 | trx_rw_is_active_low( | 265 | trx_rw_is_active_low( |
417 | 243 | /*=================*/ | 266 | /*=================*/ |
418 | 244 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | 267 | trx_id_t trx_id, /*!< in: trx id of the transaction */ |
419 | @@ -248,11 +271,9 @@ | |||
420 | 248 | Checks if a rw transaction with the given id is active. If the caller is | 271 | Checks if a rw transaction with the given id is active. If the caller is |
421 | 249 | not holding lock_sys->mutex, the transaction may already have been | 272 | not holding lock_sys->mutex, the transaction may already have been |
422 | 250 | committed. | 273 | committed. |
426 | 251 | @return transaction instance if active, or NULL; | 274 | @return true if rw transaction it with a given id is active. */ |
424 | 252 | the pointer must not be dereferenced unless lock_sys->mutex was | ||
425 | 253 | acquired before calling this function and is still being held */ | ||
427 | 254 | UNIV_INLINE | 275 | UNIV_INLINE |
429 | 255 | trx_t* | 276 | bool |
430 | 256 | trx_rw_is_active( | 277 | trx_rw_is_active( |
431 | 257 | /*=============*/ | 278 | /*=============*/ |
432 | 258 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | 279 | trx_id_t trx_id, /*!< in: trx id of the transaction */ |
433 | @@ -598,6 +619,8 @@ | |||
434 | 598 | | TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW) | 619 | | TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW) |
435 | 599 | /* @} */ | 620 | /* @} */ |
436 | 600 | 621 | ||
437 | 622 | #define TRX_DESCR_ARRAY_INITIAL_SIZE 1000 | ||
438 | 623 | |||
439 | 601 | #ifndef UNIV_HOTBACKUP | 624 | #ifndef UNIV_HOTBACKUP |
440 | 602 | /** The transaction system central memory data structure. */ | 625 | /** The transaction system central memory data structure. */ |
441 | 603 | struct trx_sys_t{ | 626 | struct trx_sys_t{ |
442 | @@ -618,6 +641,18 @@ | |||
443 | 618 | trx_id_t max_trx_id; /*!< The smallest number not yet | 641 | trx_id_t max_trx_id; /*!< The smallest number not yet |
444 | 619 | assigned as a transaction id or | 642 | assigned as a transaction id or |
445 | 620 | transaction number */ | 643 | transaction number */ |
446 | 644 | char pad1[64]; /*!< Ensure max_trx_id does not share | ||
447 | 645 | cache line with other fields. */ | ||
448 | 646 | trx_id_t* descriptors; /*!< Array of trx descriptors */ | ||
449 | 647 | ulint descr_n_max; /*!< The current size of the descriptors | ||
450 | 648 | array. */ | ||
451 | 649 | char pad2[64]; /*!< Ensure static descriptor fields | ||
452 | 650 | do not share cache lines with | ||
453 | 651 | descr_n_used */ | ||
454 | 652 | ulint descr_n_used; /*!< Number of used elements in the | ||
455 | 653 | descriptors array. */ | ||
456 | 654 | char pad3[64]; /*!< Ensure descriptors do not share | ||
457 | 655 | cache line with other fields */ | ||
458 | 621 | #ifdef UNIV_DEBUG | 656 | #ifdef UNIV_DEBUG |
459 | 622 | trx_id_t rw_max_trx_id; /*!< Max trx id of read-write transactions | 657 | trx_id_t rw_max_trx_id; /*!< Max trx id of read-write transactions |
460 | 623 | which exist or existed */ | 658 | which exist or existed */ |
461 | @@ -626,6 +661,8 @@ | |||
462 | 626 | memory read-write transactions, sorted | 661 | memory read-write transactions, sorted |
463 | 627 | on trx id, biggest first. Recovered | 662 | on trx id, biggest first. Recovered |
464 | 628 | transactions are always on this list. */ | 663 | transactions are always on this list. */ |
465 | 664 | char pad4[64]; /*!< Ensure list base nodes do not | ||
466 | 665 | share cache line with other fields */ | ||
467 | 629 | trx_list_t ro_trx_list; /*!< List of active and committed in | 666 | trx_list_t ro_trx_list; /*!< List of active and committed in |
468 | 630 | memory read-only transactions, sorted | 667 | memory read-only transactions, sorted |
469 | 631 | on trx id, biggest first. NOTE: | 668 | on trx id, biggest first. NOTE: |
470 | @@ -633,6 +670,8 @@ | |||
471 | 633 | is not necessary. We should exploit | 670 | is not necessary. We should exploit |
472 | 634 | this and increase concurrency during | 671 | this and increase concurrency during |
473 | 635 | add/remove. */ | 672 | add/remove. */ |
474 | 673 | char pad5[64]; /*!< Ensure list base nodes do not | ||
475 | 674 | share cache line with other fields */ | ||
476 | 636 | trx_list_t mysql_trx_list; /*!< List of transactions created | 675 | trx_list_t mysql_trx_list; /*!< List of transactions created |
477 | 637 | for MySQL. All transactions on | 676 | for MySQL. All transactions on |
478 | 638 | ro_trx_list are on mysql_trx_list. The | 677 | ro_trx_list are on mysql_trx_list. The |
479 | @@ -645,6 +684,15 @@ | |||
480 | 645 | mysql_trx_list may additionally contain | 684 | mysql_trx_list may additionally contain |
481 | 646 | transactions that have not yet been | 685 | transactions that have not yet been |
482 | 647 | started in InnoDB. */ | 686 | started in InnoDB. */ |
483 | 687 | char pad6[64]; /*!< Ensure list base nodes do not | ||
484 | 688 | share cache line with other fields */ | ||
485 | 689 | trx_list_t trx_serial_list; | ||
486 | 690 | /*!< trx->no ordered List of | ||
487 | 691 | transactions in either TRX_PREPARED or | ||
488 | 692 | TRX_ACTIVE which have already been | ||
489 | 693 | assigned a serialization number */ | ||
490 | 694 | char pad7[64]; /*!< Ensure list base nodes do not | ||
491 | 695 | share cache line with other fields */ | ||
492 | 648 | trx_rseg_t* const rseg_array[TRX_SYS_N_RSEGS]; | 696 | trx_rseg_t* const rseg_array[TRX_SYS_N_RSEGS]; |
493 | 649 | /*!< Pointer array to rollback | 697 | /*!< Pointer array to rollback |
494 | 650 | segments; NULL if slot not in use; | 698 | segments; NULL if slot not in use; |
495 | 651 | 699 | ||
496 | === modified file 'Percona-Server/storage/innobase/include/trx0sys.ic' | |||
497 | --- Percona-Server/storage/innobase/include/trx0sys.ic 2013-05-10 09:39:17 +0000 | |||
498 | +++ Percona-Server/storage/innobase/include/trx0sys.ic 2013-05-24 12:02:59 +0000 | |||
499 | @@ -368,16 +368,16 @@ | |||
500 | 368 | } | 368 | } |
501 | 369 | 369 | ||
502 | 370 | /****************************************************************//** | 370 | /****************************************************************//** |
507 | 371 | Checks if a rw transaction with the given id is active. Caller must hold | 371 | Returns pointer to a transaction instance if a rw transaction with the given id |
508 | 372 | trx_sys->mutex. If the caller is not holding lock_sys->mutex, the | 372 | is active. Caller must hold trx_sys->mutex. If the caller is not holding |
509 | 373 | transaction may already have been committed. | 373 | lock_sys->mutex, the transaction may already have been committed. |
510 | 374 | @return transaction instance if active, or NULL; | 374 | @return transaction instance if active, or NULL; |
511 | 375 | the pointer must not be dereferenced unless lock_sys->mutex was | 375 | the pointer must not be dereferenced unless lock_sys->mutex was |
512 | 376 | acquired before calling this function and is still being held */ | 376 | acquired before calling this function and is still being held */ |
513 | 377 | UNIV_INLINE | 377 | UNIV_INLINE |
514 | 378 | trx_t* | 378 | trx_t* |
517 | 379 | trx_rw_is_active_low( | 379 | trx_rw_get_active_trx_by_id( |
518 | 380 | /*=================*/ | 380 | /*========================*/ |
519 | 381 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | 381 | trx_id_t trx_id, /*!< in: trx id of the transaction */ |
520 | 382 | ibool* corrupt) /*!< in: NULL or pointer to a flag | 382 | ibool* corrupt) /*!< in: NULL or pointer to a flag |
521 | 383 | that will be set if corrupt */ | 383 | that will be set if corrupt */ |
522 | @@ -412,29 +412,58 @@ | |||
523 | 412 | } | 412 | } |
524 | 413 | 413 | ||
525 | 414 | /****************************************************************//** | 414 | /****************************************************************//** |
526 | 415 | Checks if a rw transaction with the given id is active. Caller must hold | ||
527 | 416 | trx_sys->mutex. If the caller is not holding lock_sys->mutex, the | ||
528 | 417 | transaction may already have been committed. | ||
529 | 418 | @return true if rw transaction it with a given id is active. */ | ||
530 | 419 | UNIV_INLINE | ||
531 | 420 | bool | ||
532 | 421 | trx_rw_is_active_low( | ||
533 | 422 | /*=================*/ | ||
534 | 423 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | ||
535 | 424 | ibool* corrupt) /*!< in: NULL or pointer to a flag | ||
536 | 425 | that will be set if corrupt */ | ||
537 | 426 | { | ||
538 | 427 | ut_ad(mutex_own(&trx_sys->mutex)); | ||
539 | 428 | |||
540 | 429 | if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) { | ||
541 | 430 | |||
542 | 431 | /* There must be corruption: we let the caller handle the | ||
543 | 432 | diagnostic prints in this case. */ | ||
544 | 433 | |||
545 | 434 | if (corrupt != NULL) { | ||
546 | 435 | *corrupt = TRUE; | ||
547 | 436 | } | ||
548 | 437 | |||
549 | 438 | return(NULL); | ||
550 | 439 | } | ||
551 | 440 | |||
552 | 441 | return(trx_find_descriptor(trx_sys->descriptors, trx_sys->descr_n_used, | ||
553 | 442 | trx_id) != NULL); | ||
554 | 443 | } | ||
555 | 444 | |||
556 | 445 | /****************************************************************//** | ||
557 | 415 | Checks if a rw transaction with the given id is active. If the caller is | 446 | Checks if a rw transaction with the given id is active. If the caller is |
558 | 416 | not holding lock_sys->mutex, the transaction may already have been | 447 | not holding lock_sys->mutex, the transaction may already have been |
559 | 417 | committed. | 448 | committed. |
563 | 418 | @return transaction instance if active, or NULL; | 449 | @return true if rw transaction it with a given id is active. */ |
561 | 419 | the pointer must not be dereferenced unless lock_sys->mutex was | ||
562 | 420 | acquired before calling this function and is still being held */ | ||
564 | 421 | UNIV_INLINE | 450 | UNIV_INLINE |
566 | 422 | trx_t* | 451 | bool |
567 | 423 | trx_rw_is_active( | 452 | trx_rw_is_active( |
568 | 424 | /*=============*/ | 453 | /*=============*/ |
569 | 425 | trx_id_t trx_id, /*!< in: trx id of the transaction */ | 454 | trx_id_t trx_id, /*!< in: trx id of the transaction */ |
570 | 426 | ibool* corrupt) /*!< in: NULL or pointer to a flag | 455 | ibool* corrupt) /*!< in: NULL or pointer to a flag |
571 | 427 | that will be set if corrupt */ | 456 | that will be set if corrupt */ |
572 | 428 | { | 457 | { |
574 | 429 | trx_t* trx; | 458 | bool res; |
575 | 430 | 459 | ||
576 | 431 | mutex_enter(&trx_sys->mutex); | 460 | mutex_enter(&trx_sys->mutex); |
577 | 432 | 461 | ||
579 | 433 | trx = trx_rw_is_active_low(trx_id, corrupt); | 462 | res = trx_rw_is_active_low(trx_id, corrupt); |
580 | 434 | 463 | ||
581 | 435 | mutex_exit(&trx_sys->mutex); | 464 | mutex_exit(&trx_sys->mutex); |
582 | 436 | 465 | ||
584 | 437 | return(trx); | 466 | return(res); |
585 | 438 | } | 467 | } |
586 | 439 | 468 | ||
587 | 440 | /*****************************************************************//** | 469 | /*****************************************************************//** |
588 | @@ -509,4 +538,28 @@ | |||
589 | 509 | 538 | ||
590 | 510 | return(n_trx); | 539 | return(n_trx); |
591 | 511 | } | 540 | } |
592 | 541 | |||
593 | 542 | |||
594 | 543 | /*************************************************************//** | ||
595 | 544 | Find a slot for a given trx ID in a descriptors array. | ||
596 | 545 | @return: slot pointer */ | ||
597 | 546 | UNIV_INLINE | ||
598 | 547 | trx_id_t* | ||
599 | 548 | trx_find_descriptor( | ||
600 | 549 | /*================*/ | ||
601 | 550 | const trx_id_t* descriptors, /*!< in: descriptors array */ | ||
602 | 551 | ulint n_descr, /*!< in: array size */ | ||
603 | 552 | trx_id_t trx_id) /*!< in: trx id */ | ||
604 | 553 | { | ||
605 | 554 | ut_ad(descriptors != trx_sys->descriptors || | ||
606 | 555 | mutex_own(&trx_sys->mutex)); | ||
607 | 556 | |||
608 | 557 | if (UNIV_UNLIKELY(n_descr == 0)) { | ||
609 | 558 | |||
610 | 559 | return(NULL); | ||
611 | 560 | } | ||
612 | 561 | |||
613 | 562 | return((trx_id_t *) bsearch(&trx_id, descriptors, n_descr, | ||
614 | 563 | sizeof(trx_id_t), trx_descr_cmp)); | ||
615 | 564 | } | ||
616 | 512 | #endif /* !UNIV_HOTBACKUP */ | 565 | #endif /* !UNIV_HOTBACKUP */ |
617 | 513 | 566 | ||
618 | === modified file 'Percona-Server/storage/innobase/include/trx0trx.h' | |||
619 | --- Percona-Server/storage/innobase/include/trx0trx.h 2013-05-23 06:51:50 +0000 | |||
620 | +++ Percona-Server/storage/innobase/include/trx0trx.h 2013-05-24 12:02:59 +0000 | |||
621 | @@ -459,6 +459,24 @@ | |||
622 | 459 | /*============*/ | 459 | /*============*/ |
623 | 460 | trx_t* trx); /*!< A read-only transaction that | 460 | trx_t* trx); /*!< A read-only transaction that |
624 | 461 | needs to be assigned a RBS. */ | 461 | needs to be assigned a RBS. */ |
625 | 462 | |||
626 | 463 | /*************************************************************//** | ||
627 | 464 | Callback function for trx_find_descriptor() to compare trx IDs. */ | ||
628 | 465 | UNIV_INTERN | ||
629 | 466 | int | ||
630 | 467 | trx_descr_cmp( | ||
631 | 468 | /*==========*/ | ||
632 | 469 | const void *a, /*!< in: pointer to first comparison argument */ | ||
633 | 470 | const void *b); /*!< in: pointer to second comparison argument */ | ||
634 | 471 | |||
635 | 472 | /*************************************************************//** | ||
636 | 473 | Release a slot for a given trx in the global descriptors array. */ | ||
637 | 474 | UNIV_INTERN | ||
638 | 475 | void | ||
639 | 476 | trx_release_descriptor( | ||
640 | 477 | /*===================*/ | ||
641 | 478 | trx_t* trx); /*!< in: trx pointer */ | ||
642 | 479 | |||
643 | 462 | /*******************************************************************//** | 480 | /*******************************************************************//** |
644 | 463 | Transactions that aren't started by the MySQL server don't set | 481 | Transactions that aren't started by the MySQL server don't set |
645 | 464 | the trx_t::mysql_thd field. For such transactions we set the lock | 482 | the trx_t::mysql_thd field. For such transactions we set the lock |
646 | @@ -892,6 +910,12 @@ | |||
647 | 892 | /*!< TRUE if in | 910 | /*!< TRUE if in |
648 | 893 | trx_sys->mysql_trx_list */ | 911 | trx_sys->mysql_trx_list */ |
649 | 894 | #endif /* UNIV_DEBUG */ | 912 | #endif /* UNIV_DEBUG */ |
650 | 913 | UT_LIST_NODE_T(trx_t) | ||
651 | 914 | trx_serial_list;/*!< list node for | ||
652 | 915 | trx_sys->trx_serial_list */ | ||
653 | 916 | ibool in_trx_serial_list; | ||
654 | 917 | /* Set when transaction is in the | ||
655 | 918 | trx_serial_list */ | ||
656 | 895 | /*------------------------------*/ | 919 | /*------------------------------*/ |
657 | 896 | dberr_t error_state; /*!< 0 if no error, otherwise error | 920 | dberr_t error_state; /*!< 0 if no error, otherwise error |
658 | 897 | number; NOTE That ONLY the thread | 921 | number; NOTE That ONLY the thread |
659 | 898 | 922 | ||
660 | === modified file 'Percona-Server/storage/innobase/lock/lock0lock.cc' | |||
661 | --- Percona-Server/storage/innobase/lock/lock0lock.cc 2013-05-12 09:13:00 +0000 | |||
662 | +++ Percona-Server/storage/innobase/lock/lock0lock.cc 2013-05-24 12:02:59 +0000 | |||
663 | @@ -5556,7 +5556,7 @@ | |||
664 | 5556 | if the check and assertion are covered by the lock mutex. */ | 5556 | if the check and assertion are covered by the lock mutex. */ |
665 | 5557 | 5557 | ||
666 | 5558 | trx_id = lock_clust_rec_some_has_impl(rec, index, offsets); | 5558 | trx_id = lock_clust_rec_some_has_impl(rec, index, offsets); |
668 | 5559 | impl_trx = trx_rw_is_active_low(trx_id, NULL); | 5559 | impl_trx = trx_rw_get_active_trx_by_id(trx_id, NULL); |
669 | 5560 | 5560 | ||
670 | 5561 | ut_ad(lock_mutex_own()); | 5561 | ut_ad(lock_mutex_own()); |
671 | 5562 | /* impl_trx cannot be committed until lock_mutex_exit() | 5562 | /* impl_trx cannot be committed until lock_mutex_exit() |
672 | @@ -6055,7 +6055,9 @@ | |||
673 | 6055 | /* If the transaction is still active and has no | 6055 | /* If the transaction is still active and has no |
674 | 6056 | explicit x-lock set on the record, set one for it */ | 6056 | explicit x-lock set on the record, set one for it */ |
675 | 6057 | 6057 | ||
677 | 6058 | impl_trx = trx_rw_is_active(trx_id, NULL); | 6058 | mutex_enter(&trx_sys->mutex); |
678 | 6059 | impl_trx = trx_rw_get_active_trx_by_id(trx_id, NULL); | ||
679 | 6060 | mutex_exit(&trx_sys->mutex); | ||
680 | 6059 | 6061 | ||
681 | 6060 | /* impl_trx cannot be committed until lock_mutex_exit() | 6062 | /* impl_trx cannot be committed until lock_mutex_exit() |
682 | 6061 | because lock_trx_release_locks() acquires lock_sys->mutex */ | 6063 | because lock_trx_release_locks() acquires lock_sys->mutex */ |
683 | @@ -6843,8 +6845,12 @@ | |||
684 | 6843 | } | 6845 | } |
685 | 6844 | 6846 | ||
686 | 6845 | /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY | 6847 | /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY |
688 | 6846 | is protected by both the lock_sys->mutex and the trx->mutex. */ | 6848 | is protected by both the lock_sys->mutex and the trx->mutex. |
689 | 6849 | We also lock trx_sys->mutex, because state transition to | ||
690 | 6850 | TRX_STATE_COMMITTED_IN_MEMORY must be atomic with removing trx | ||
691 | 6851 | from the descriptors array. */ | ||
692 | 6847 | lock_mutex_enter(); | 6852 | lock_mutex_enter(); |
693 | 6853 | mutex_enter(&trx_sys->mutex); | ||
694 | 6848 | trx_mutex_enter(trx); | 6854 | trx_mutex_enter(trx); |
695 | 6849 | 6855 | ||
696 | 6850 | /* The following assignment makes the transaction committed in memory | 6856 | /* The following assignment makes the transaction committed in memory |
697 | @@ -6863,6 +6869,8 @@ | |||
698 | 6863 | 6869 | ||
699 | 6864 | /*--------------------------------------*/ | 6870 | /*--------------------------------------*/ |
700 | 6865 | trx->state = TRX_STATE_COMMITTED_IN_MEMORY; | 6871 | trx->state = TRX_STATE_COMMITTED_IN_MEMORY; |
701 | 6872 | /* The following also removes trx from trx_serial_list */ | ||
702 | 6873 | trx_release_descriptor(trx); | ||
703 | 6866 | /*--------------------------------------*/ | 6874 | /*--------------------------------------*/ |
704 | 6867 | 6875 | ||
705 | 6868 | /* If the background thread trx_rollback_or_clean_recovered() | 6876 | /* If the background thread trx_rollback_or_clean_recovered() |
706 | @@ -6880,6 +6888,8 @@ | |||
707 | 6880 | 6888 | ||
708 | 6881 | trx_mutex_exit(trx); | 6889 | trx_mutex_exit(trx); |
709 | 6882 | 6890 | ||
710 | 6891 | mutex_exit(&trx_sys->mutex); | ||
711 | 6892 | |||
712 | 6883 | lock_release(trx); | 6893 | lock_release(trx); |
713 | 6884 | 6894 | ||
714 | 6885 | lock_mutex_exit(); | 6895 | lock_mutex_exit(); |
715 | 6886 | 6896 | ||
716 | === modified file 'Percona-Server/storage/innobase/read/read0read.cc' | |||
717 | --- Percona-Server/storage/innobase/read/read0read.cc 2013-05-23 06:51:50 +0000 | |||
718 | +++ Percona-Server/storage/innobase/read/read0read.cc 2013-05-24 12:02:59 +0000 | |||
719 | @@ -189,23 +189,23 @@ | |||
720 | 189 | if (view == NULL) { | 189 | if (view == NULL) { |
721 | 190 | view = static_cast<read_view_t*>( | 190 | view = static_cast<read_view_t*>( |
722 | 191 | ut_malloc(sizeof(read_view_t))); | 191 | ut_malloc(sizeof(read_view_t))); |
725 | 192 | view->max_trx_ids = 0; | 192 | view->max_descr = 0; |
726 | 193 | view->trx_ids = NULL; | 193 | view->descriptors = NULL; |
727 | 194 | } | 194 | } |
728 | 195 | 195 | ||
730 | 196 | if (UNIV_UNLIKELY(view->max_trx_ids < n)) { | 196 | if (UNIV_UNLIKELY(view->max_descr < n)) { |
731 | 197 | 197 | ||
733 | 198 | /* avoid frequent reallocations by extending the array to the | 198 | /* avoid frequent re-allocations by extending the array to the |
734 | 199 | desired size + 10% */ | 199 | desired size + 10% */ |
735 | 200 | 200 | ||
741 | 201 | view->max_trx_ids = n + n / 10; | 201 | view->max_descr = n + n / 10; |
742 | 202 | view->trx_ids = static_cast<trx_id_t*>( | 202 | view->descriptors = static_cast<trx_id_t*>( |
743 | 203 | ut_realloc(view->trx_ids, | 203 | ut_realloc(view->descriptors, |
744 | 204 | view->max_trx_ids * | 204 | view->max_descr * |
745 | 205 | sizeof *view->trx_ids)); | 205 | sizeof *view->descriptors)); |
746 | 206 | } | 206 | } |
747 | 207 | 207 | ||
749 | 208 | view->n_trx_ids = n; | 208 | view->n_descr = n; |
750 | 209 | 209 | ||
751 | 210 | return(view); | 210 | return(view); |
752 | 211 | } | 211 | } |
753 | @@ -225,24 +225,24 @@ | |||
754 | 225 | NULL */ | 225 | NULL */ |
755 | 226 | { | 226 | { |
756 | 227 | read_view_t* clone; | 227 | read_view_t* clone; |
759 | 228 | trx_id_t* old_trx_ids; | 228 | trx_id_t* old_descriptors; |
760 | 229 | ulint old_max_trx_ids; | 229 | ulint old_max_descr; |
761 | 230 | 230 | ||
762 | 231 | ut_ad(mutex_own(&trx_sys->mutex)); | 231 | ut_ad(mutex_own(&trx_sys->mutex)); |
763 | 232 | 232 | ||
765 | 233 | clone = read_view_create_low(view->n_trx_ids, prebuilt_clone); | 233 | clone = read_view_create_low(view->n_descr, prebuilt_clone); |
766 | 234 | 234 | ||
769 | 235 | old_trx_ids = clone->trx_ids; | 235 | old_descriptors = clone->descriptors; |
770 | 236 | old_max_trx_ids = clone->max_trx_ids; | 236 | old_max_descr = clone->max_descr; |
771 | 237 | 237 | ||
772 | 238 | memcpy(clone, view, sizeof(*view)); | 238 | memcpy(clone, view, sizeof(*view)); |
773 | 239 | 239 | ||
776 | 240 | clone->trx_ids = old_trx_ids; | 240 | clone->descriptors = old_descriptors; |
777 | 241 | clone->max_trx_ids = old_max_trx_ids; | 241 | clone->max_descr = old_max_descr; |
778 | 242 | 242 | ||
782 | 243 | if (view->n_trx_ids) { | 243 | if (view->n_descr) { |
783 | 244 | memcpy(clone->trx_ids, view->trx_ids, | 244 | memcpy(clone->descriptors, view->descriptors, |
784 | 245 | view->n_trx_ids * sizeof(trx_id_t)); | 245 | view->n_descr * sizeof(trx_id_t)); |
785 | 246 | } | 246 | } |
786 | 247 | 247 | ||
787 | 248 | return(clone); | 248 | return(clone); |
788 | @@ -280,53 +280,6 @@ | |||
789 | 280 | ut_ad(read_view_list_validate()); | 280 | ut_ad(read_view_list_validate()); |
790 | 281 | } | 281 | } |
791 | 282 | 282 | ||
792 | 283 | /** Functor to create thew view trx_ids array. */ | ||
793 | 284 | struct CreateView { | ||
794 | 285 | |||
795 | 286 | CreateView(read_view_t* view) | ||
796 | 287 | : m_view(view) | ||
797 | 288 | { | ||
798 | 289 | m_n_trx = m_view->n_trx_ids; | ||
799 | 290 | m_view->n_trx_ids = 0; | ||
800 | 291 | } | ||
801 | 292 | |||
802 | 293 | void operator()(const trx_t* trx) | ||
803 | 294 | { | ||
804 | 295 | ut_ad(mutex_own(&trx_sys->mutex)); | ||
805 | 296 | ut_ad(trx->in_rw_trx_list); | ||
806 | 297 | |||
807 | 298 | /* trx->state cannot change from or to NOT_STARTED | ||
808 | 299 | while we are holding the trx_sys->mutex. It may change | ||
809 | 300 | from ACTIVE to PREPARED or COMMITTED. */ | ||
810 | 301 | |||
811 | 302 | if (trx->id != m_view->creator_trx_id | ||
812 | 303 | && !trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)) { | ||
813 | 304 | |||
814 | 305 | ut_ad(m_n_trx > m_view->n_trx_ids); | ||
815 | 306 | |||
816 | 307 | m_view->trx_ids[m_view->n_trx_ids++] = trx->id; | ||
817 | 308 | |||
818 | 309 | /* NOTE that a transaction whose trx number is < | ||
819 | 310 | trx_sys->max_trx_id can still be active, if it is | ||
820 | 311 | in the middle of its commit! Note that when a | ||
821 | 312 | transaction starts, we initialize trx->no to | ||
822 | 313 | IB_ULONGLONG_MAX. */ | ||
823 | 314 | |||
824 | 315 | /* trx->no is protected by trx_sys->mutex, which | ||
825 | 316 | we are holding. It is assigned by trx_commit() | ||
826 | 317 | before lock_trx_release_locks() assigns | ||
827 | 318 | trx->state = TRX_STATE_COMMITTED_IN_MEMORY. */ | ||
828 | 319 | |||
829 | 320 | if (m_view->low_limit_no > trx->no) { | ||
830 | 321 | m_view->low_limit_no = trx->no; | ||
831 | 322 | } | ||
832 | 323 | } | ||
833 | 324 | } | ||
834 | 325 | |||
835 | 326 | read_view_t* m_view; | ||
836 | 327 | ulint m_n_trx; | ||
837 | 328 | }; | ||
838 | 329 | |||
839 | 330 | /*********************************************************************//** | 283 | /*********************************************************************//** |
840 | 331 | Opens a read view where exactly the transactions serialized before this | 284 | Opens a read view where exactly the transactions serialized before this |
841 | 332 | point in time are seen in the view. | 285 | point in time are seen in the view. |
842 | @@ -340,11 +293,12 @@ | |||
843 | 340 | read_view_t*& view) /*!< in,out: pre-allocated view array or | 293 | read_view_t*& view) /*!< in,out: pre-allocated view array or |
844 | 341 | NULL if a new one needs to be created */ | 294 | NULL if a new one needs to be created */ |
845 | 342 | { | 295 | { |
847 | 343 | ulint n_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); | 296 | trx_id_t* descr; |
848 | 297 | ulint i; | ||
849 | 344 | 298 | ||
850 | 345 | ut_ad(mutex_own(&trx_sys->mutex)); | 299 | ut_ad(mutex_own(&trx_sys->mutex)); |
851 | 346 | 300 | ||
853 | 347 | view = read_view_create_low(n_trx, view); | 301 | view = read_view_create_low(trx_sys->descr_n_used, view); |
854 | 348 | 302 | ||
855 | 349 | view->undo_no = 0; | 303 | view->undo_no = 0; |
856 | 350 | view->type = VIEW_NORMAL; | 304 | view->type = VIEW_NORMAL; |
857 | @@ -355,13 +309,52 @@ | |||
858 | 355 | view->low_limit_no = trx_sys->max_trx_id; | 309 | view->low_limit_no = trx_sys->max_trx_id; |
859 | 356 | view->low_limit_id = view->low_limit_no; | 310 | view->low_limit_id = view->low_limit_no; |
860 | 357 | 311 | ||
866 | 358 | /* No active transaction should be visible, except cr_trx */ | 312 | descr = trx_find_descriptor(trx_sys->descriptors, |
867 | 359 | 313 | trx_sys->descr_n_used, | |
868 | 360 | ut_list_map(trx_sys->rw_trx_list, &trx_t::trx_list, CreateView(view)); | 314 | cr_trx_id); |
869 | 361 | 315 | if (UNIV_LIKELY(descr != NULL)) { | |
870 | 362 | if (view->n_trx_ids > 0) { | 316 | ut_ad(trx_sys->descr_n_used > 0); |
871 | 317 | ut_ad(view->n_descr > 0); | ||
872 | 318 | |||
873 | 319 | view->n_descr--; | ||
874 | 320 | |||
875 | 321 | i = descr - trx_sys->descriptors; | ||
876 | 322 | } else { | ||
877 | 323 | i = trx_sys->descr_n_used; | ||
878 | 324 | } | ||
879 | 325 | |||
880 | 326 | if (UNIV_LIKELY(i > 0)) { | ||
881 | 327 | /* Copy the [0; i-1] range */ | ||
882 | 328 | memcpy(view->descriptors, trx_sys->descriptors, | ||
883 | 329 | i * sizeof(trx_id_t)); | ||
884 | 330 | } | ||
885 | 331 | |||
886 | 332 | if (UNIV_UNLIKELY(i + 1 < trx_sys->descr_n_used)) { | ||
887 | 333 | /* Copy the [i+1; descr_n_used-1] range */ | ||
888 | 334 | memcpy(view->descriptors + i, | ||
889 | 335 | trx_sys->descriptors + i + 1, | ||
890 | 336 | (trx_sys->descr_n_used - i - 1) * | ||
891 | 337 | sizeof(trx_id_t)); | ||
892 | 338 | } | ||
893 | 339 | |||
894 | 340 | /* NOTE that a transaction whose trx number is < trx_sys->max_trx_id can | ||
895 | 341 | still be active, if it is in the middle of its commit! Note that when a | ||
896 | 342 | transaction starts, we initialize trx->no to IB_ULONGLONG_MAX. */ | ||
897 | 343 | |||
898 | 344 | if (UT_LIST_GET_LEN(trx_sys->trx_serial_list) > 0) { | ||
899 | 345 | |||
900 | 346 | trx_id_t trx_no; | ||
901 | 347 | |||
902 | 348 | trx_no = UT_LIST_GET_FIRST(trx_sys->trx_serial_list)->no; | ||
903 | 349 | |||
904 | 350 | if (trx_no < view->low_limit_no) { | ||
905 | 351 | view->low_limit_no = trx_no; | ||
906 | 352 | } | ||
907 | 353 | } | ||
908 | 354 | |||
909 | 355 | if (UNIV_LIKELY(view->n_descr > 0)) { | ||
910 | 363 | /* The last active transaction has the smallest id: */ | 356 | /* The last active transaction has the smallest id: */ |
912 | 364 | view->up_limit_id = view->trx_ids[view->n_trx_ids - 1]; | 357 | view->up_limit_id = view->descriptors[0]; |
913 | 365 | } else { | 358 | } else { |
914 | 366 | view->up_limit_id = view->low_limit_id; | 359 | view->up_limit_id = view->low_limit_id; |
915 | 367 | } | 360 | } |
916 | @@ -442,29 +435,29 @@ | |||
917 | 442 | ut_a(oldest_view->creator_trx_id > 0); | 435 | ut_a(oldest_view->creator_trx_id > 0); |
918 | 443 | creator_trx_id = oldest_view->creator_trx_id; | 436 | creator_trx_id = oldest_view->creator_trx_id; |
919 | 444 | 437 | ||
921 | 445 | view = read_view_create_low(oldest_view->n_trx_ids + 1, prebuilt_view); | 438 | view = read_view_create_low(oldest_view->n_descr + 1, prebuilt_view); |
922 | 446 | 439 | ||
923 | 447 | /* Add the creator transaction id in the trx_ids array in the | 440 | /* Add the creator transaction id in the trx_ids array in the |
924 | 448 | correct slot. */ | 441 | correct slot. */ |
925 | 449 | 442 | ||
927 | 450 | for (i = 0; i < oldest_view->n_trx_ids; ++i) { | 443 | for (i = 0; i < oldest_view->n_descr; ++i) { |
928 | 451 | trx_id_t id; | 444 | trx_id_t id; |
929 | 452 | 445 | ||
931 | 453 | id = oldest_view->trx_ids[i - insert_done]; | 446 | id = oldest_view->descriptors[i - insert_done]; |
932 | 454 | 447 | ||
934 | 455 | if (insert_done == 0 && creator_trx_id > id) { | 448 | if (insert_done == 0 && creator_trx_id < id) { |
935 | 456 | id = creator_trx_id; | 449 | id = creator_trx_id; |
936 | 457 | insert_done = 1; | 450 | insert_done = 1; |
937 | 458 | } | 451 | } |
938 | 459 | 452 | ||
940 | 460 | view->trx_ids[i] = id; | 453 | view->descriptors[i] = id; |
941 | 461 | } | 454 | } |
942 | 462 | 455 | ||
943 | 463 | if (insert_done == 0) { | 456 | if (insert_done == 0) { |
945 | 464 | view->trx_ids[i] = creator_trx_id; | 457 | view->descriptors[i] = creator_trx_id; |
946 | 465 | } else { | 458 | } else { |
947 | 466 | ut_a(i > 0); | 459 | ut_a(i > 0); |
949 | 467 | view->trx_ids[i] = oldest_view->trx_ids[i - 1]; | 460 | view->descriptors[i] = oldest_view->descriptors[i - 1]; |
950 | 468 | } | 461 | } |
951 | 469 | 462 | ||
952 | 470 | view->creator_trx_id = 0; | 463 | view->creator_trx_id = 0; |
953 | @@ -472,10 +465,10 @@ | |||
954 | 472 | view->low_limit_no = oldest_view->low_limit_no; | 465 | view->low_limit_no = oldest_view->low_limit_no; |
955 | 473 | view->low_limit_id = oldest_view->low_limit_id; | 466 | view->low_limit_id = oldest_view->low_limit_id; |
956 | 474 | 467 | ||
958 | 475 | if (view->n_trx_ids > 0) { | 468 | if (view->n_descr > 0) { |
959 | 476 | /* The last active transaction has the smallest id: */ | 469 | /* The last active transaction has the smallest id: */ |
960 | 477 | 470 | ||
962 | 478 | view->up_limit_id = view->trx_ids[view->n_trx_ids - 1]; | 471 | view->up_limit_id = view->descriptors[0]; |
963 | 479 | } else { | 472 | } else { |
964 | 480 | view->up_limit_id = oldest_view->up_limit_id; | 473 | view->up_limit_id = oldest_view->up_limit_id; |
965 | 481 | } | 474 | } |
966 | @@ -531,11 +524,11 @@ | |||
967 | 531 | 524 | ||
968 | 532 | fprintf(file, "Read view individually stored trx ids:\n"); | 525 | fprintf(file, "Read view individually stored trx ids:\n"); |
969 | 533 | 526 | ||
971 | 534 | n_ids = view->n_trx_ids; | 527 | n_ids = view->n_descr; |
972 | 535 | 528 | ||
973 | 536 | for (i = 0; i < n_ids; i++) { | 529 | for (i = 0; i < n_ids; i++) { |
974 | 537 | fprintf(file, "Read view trx id " TRX_ID_FMT "\n", | 530 | fprintf(file, "Read view trx id " TRX_ID_FMT "\n", |
976 | 538 | view->trx_ids[i]); | 531 | view->descriptors[i]); |
977 | 539 | } | 532 | } |
978 | 540 | } | 533 | } |
979 | 541 | 534 | ||
980 | @@ -582,8 +575,8 @@ | |||
981 | 582 | return; | 575 | return; |
982 | 583 | } | 576 | } |
983 | 584 | 577 | ||
986 | 585 | if (view->trx_ids != NULL) { | 578 | if (view->descriptors != NULL) { |
987 | 586 | ut_free(view->trx_ids); | 579 | ut_free(view->descriptors); |
988 | 587 | } | 580 | } |
989 | 588 | 581 | ||
990 | 589 | ut_free(view); | 582 | ut_free(view); |
991 | @@ -604,7 +597,6 @@ | |||
992 | 604 | { | 597 | { |
993 | 605 | read_view_t* view; | 598 | read_view_t* view; |
994 | 606 | mem_heap_t* heap; | 599 | mem_heap_t* heap; |
995 | 607 | ulint n_trx; | ||
996 | 608 | cursor_view_t* curview; | 600 | cursor_view_t* curview; |
997 | 609 | 601 | ||
998 | 610 | /* Use larger heap than in trx_create when creating a read_view | 602 | /* Use larger heap than in trx_create when creating a read_view |
999 | @@ -625,36 +617,12 @@ | |||
1000 | 625 | 617 | ||
1001 | 626 | mutex_enter(&trx_sys->mutex); | 618 | mutex_enter(&trx_sys->mutex); |
1002 | 627 | 619 | ||
1003 | 628 | n_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); | ||
1004 | 629 | |||
1005 | 630 | curview->read_view = NULL; | 620 | curview->read_view = NULL; |
1007 | 631 | read_view_create_low(n_trx, curview->read_view); | 621 | read_view_open_now_low(UINT64_UNDEFINED, curview->read_view); |
1008 | 632 | 622 | ||
1009 | 633 | view = curview->read_view; | 623 | view = curview->read_view; |
1010 | 634 | view->undo_no = cr_trx->undo_no; | 624 | view->undo_no = cr_trx->undo_no; |
1011 | 635 | view->type = VIEW_HIGH_GRANULARITY; | 625 | view->type = VIEW_HIGH_GRANULARITY; |
1012 | 636 | view->creator_trx_id = UINT64_UNDEFINED; | ||
1013 | 637 | |||
1014 | 638 | /* No future transactions should be visible in the view */ | ||
1015 | 639 | |||
1016 | 640 | view->low_limit_no = trx_sys->max_trx_id; | ||
1017 | 641 | view->low_limit_id = view->low_limit_no; | ||
1018 | 642 | |||
1019 | 643 | /* No active transaction should be visible */ | ||
1020 | 644 | |||
1021 | 645 | ut_list_map(trx_sys->rw_trx_list, &trx_t::trx_list, CreateView(view)); | ||
1022 | 646 | |||
1023 | 647 | view->creator_trx_id = cr_trx->id; | ||
1024 | 648 | |||
1025 | 649 | if (view->n_trx_ids > 0) { | ||
1026 | 650 | /* The last active transaction has the smallest id: */ | ||
1027 | 651 | |||
1028 | 652 | view->up_limit_id = view->trx_ids[view->n_trx_ids - 1]; | ||
1029 | 653 | } else { | ||
1030 | 654 | view->up_limit_id = view->low_limit_id; | ||
1031 | 655 | } | ||
1032 | 656 | |||
1033 | 657 | read_view_add(view); | ||
1034 | 658 | 626 | ||
1035 | 659 | mutex_exit(&trx_sys->mutex); | 627 | mutex_exit(&trx_sys->mutex); |
1036 | 660 | 628 | ||
1037 | 661 | 629 | ||
1038 | === modified file 'Percona-Server/storage/innobase/row/row0sel.cc' | |||
1039 | --- Percona-Server/storage/innobase/row/row0sel.cc 2013-05-23 06:51:50 +0000 | |||
1040 | +++ Percona-Server/storage/innobase/row/row0sel.cc 2013-05-24 12:02:59 +0000 | |||
1041 | @@ -5205,8 +5205,8 @@ | |||
1042 | 5205 | if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ | 5205 | if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ |
1043 | 5206 | && !trx->read_view) { | 5206 | && !trx->read_view) { |
1044 | 5207 | 5207 | ||
1047 | 5208 | trx->read_view = read_view_open_now( | 5208 | trx->read_view = read_view_open_now(trx->id, |
1048 | 5209 | trx->id, trx->prebuilt_view); | 5209 | trx->prebuilt_view); |
1049 | 5210 | 5210 | ||
1050 | 5211 | trx->global_read_view = trx->read_view; | 5211 | trx->global_read_view = trx->read_view; |
1051 | 5212 | } | 5212 | } |
1052 | 5213 | 5213 | ||
1053 | === modified file 'Percona-Server/storage/innobase/row/row0vers.cc' | |||
1054 | --- Percona-Server/storage/innobase/row/row0vers.cc 2013-05-10 09:39:17 +0000 | |||
1055 | +++ Percona-Server/storage/innobase/row/row0vers.cc 2013-05-24 12:02:59 +0000 | |||
1056 | @@ -646,7 +646,7 @@ | |||
1057 | 646 | version = rec; | 646 | version = rec; |
1058 | 647 | 647 | ||
1059 | 648 | for (;;) { | 648 | for (;;) { |
1061 | 649 | const trx_t* version_trx; | 649 | trx_id_t* version_trx_descr; |
1062 | 650 | mem_heap_t* heap2; | 650 | mem_heap_t* heap2; |
1063 | 651 | rec_t* prev_version; | 651 | rec_t* prev_version; |
1064 | 652 | trx_id_t version_trx_id; | 652 | trx_id_t version_trx_id; |
1065 | @@ -657,19 +657,16 @@ | |||
1066 | 657 | } | 657 | } |
1067 | 658 | 658 | ||
1068 | 659 | mutex_enter(&trx_sys->mutex); | 659 | mutex_enter(&trx_sys->mutex); |
1070 | 660 | version_trx = trx_get_rw_trx_by_id(version_trx_id); | 660 | version_trx_descr = trx_find_descriptor(trx_sys->descriptors, |
1071 | 661 | trx_sys->descr_n_used, | ||
1072 | 662 | version_trx_id); | ||
1073 | 661 | /* Because version_trx is a read-write transaction, | 663 | /* Because version_trx is a read-write transaction, |
1074 | 662 | its state cannot change from or to NOT_STARTED while | 664 | its state cannot change from or to NOT_STARTED while |
1075 | 663 | we are holding the trx_sys->mutex. It may change from | 665 | we are holding the trx_sys->mutex. It may change from |
1076 | 664 | ACTIVE to PREPARED or COMMITTED. */ | 666 | ACTIVE to PREPARED or COMMITTED. */ |
1077 | 665 | if (version_trx | ||
1078 | 666 | && trx_state_eq(version_trx, | ||
1079 | 667 | TRX_STATE_COMMITTED_IN_MEMORY)) { | ||
1080 | 668 | version_trx = NULL; | ||
1081 | 669 | } | ||
1082 | 670 | mutex_exit(&trx_sys->mutex); | 667 | mutex_exit(&trx_sys->mutex); |
1083 | 671 | 668 | ||
1085 | 672 | if (!version_trx) { | 669 | if (!version_trx_descr) { |
1086 | 673 | committed_version_trx: | 670 | committed_version_trx: |
1087 | 674 | /* We found a version that belongs to a | 671 | /* We found a version that belongs to a |
1088 | 675 | committed transaction: return it. */ | 672 | committed transaction: return it. */ |
1089 | 676 | 673 | ||
1090 | === modified file 'Percona-Server/storage/innobase/trx/trx0sys.cc' | |||
1091 | --- Percona-Server/storage/innobase/trx/trx0sys.cc 2013-05-12 06:24:46 +0000 | |||
1092 | +++ Percona-Server/storage/innobase/trx/trx0sys.cc 2013-05-24 12:02:59 +0000 | |||
1093 | @@ -506,6 +506,13 @@ | |||
1094 | 506 | 506 | ||
1095 | 507 | mtr_start(&mtr); | 507 | mtr_start(&mtr); |
1096 | 508 | 508 | ||
1097 | 509 | /* Allocate the trx descriptors array */ | ||
1098 | 510 | trx_sys->descriptors = static_cast<trx_id_t*>( | ||
1099 | 511 | ut_malloc(sizeof(trx_id_t) * | ||
1100 | 512 | TRX_DESCR_ARRAY_INITIAL_SIZE)); | ||
1101 | 513 | trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE; | ||
1102 | 514 | trx_sys->descr_n_used = 0; | ||
1103 | 515 | |||
1104 | 509 | sys_header = trx_sysf_get(&mtr); | 516 | sys_header = trx_sysf_get(&mtr); |
1105 | 510 | 517 | ||
1106 | 511 | if (srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { | 518 | if (srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { |
1107 | @@ -1232,6 +1239,9 @@ | |||
1108 | 1232 | 1239 | ||
1109 | 1233 | mutex_free(&trx_sys->mutex); | 1240 | mutex_free(&trx_sys->mutex); |
1110 | 1234 | 1241 | ||
1111 | 1242 | ut_ad(trx_sys->descr_n_used == 0); | ||
1112 | 1243 | ut_free(trx_sys->descriptors); | ||
1113 | 1244 | |||
1114 | 1235 | mem_free(trx_sys); | 1245 | mem_free(trx_sys); |
1115 | 1236 | 1246 | ||
1116 | 1237 | trx_sys = NULL; | 1247 | trx_sys = NULL; |
1117 | 1238 | 1248 | ||
1118 | === modified file 'Percona-Server/storage/innobase/trx/trx0trx.cc' | |||
1119 | --- Percona-Server/storage/innobase/trx/trx0trx.cc 2013-05-23 06:51:50 +0000 | |||
1120 | +++ Percona-Server/storage/innobase/trx/trx0trx.cc 2013-05-24 12:02:59 +0000 | |||
1121 | @@ -83,6 +83,127 @@ | |||
1122 | 83 | sizeof(trx->detailed_error)); | 83 | sizeof(trx->detailed_error)); |
1123 | 84 | } | 84 | } |
1124 | 85 | 85 | ||
1125 | 86 | /*************************************************************//** | ||
1126 | 87 | Callback function for trx_find_descriptor() to compare trx IDs. */ | ||
1127 | 88 | UNIV_INTERN | ||
1128 | 89 | int | ||
1129 | 90 | trx_descr_cmp( | ||
1130 | 91 | /*==========*/ | ||
1131 | 92 | const void *a, /*!< in: pointer to first comparison argument */ | ||
1132 | 93 | const void *b) /*!< in: pointer to second comparison argument */ | ||
1133 | 94 | { | ||
1134 | 95 | const trx_id_t* da = (const trx_id_t*) a; | ||
1135 | 96 | const trx_id_t* db = (const trx_id_t*) b; | ||
1136 | 97 | |||
1137 | 98 | if (*da < *db) { | ||
1138 | 99 | return -1; | ||
1139 | 100 | } else if (*da > *db) { | ||
1140 | 101 | return 1; | ||
1141 | 102 | } | ||
1142 | 103 | |||
1143 | 104 | return 0; | ||
1144 | 105 | } | ||
1145 | 106 | |||
1146 | 107 | /*************************************************************//** | ||
1147 | 108 | Reserve a slot for a given trx in the global descriptors array. */ | ||
1148 | 109 | UNIV_INLINE | ||
1149 | 110 | void | ||
1150 | 111 | trx_reserve_descriptor( | ||
1151 | 112 | /*===================*/ | ||
1152 | 113 | const trx_t* trx) /*!< in: trx pointer */ | ||
1153 | 114 | { | ||
1154 | 115 | ulint n_used; | ||
1155 | 116 | ulint n_max; | ||
1156 | 117 | trx_id_t* descr; | ||
1157 | 118 | |||
1158 | 119 | ut_ad(mutex_own(&trx_sys->mutex) || srv_is_being_started); | ||
1159 | 120 | ut_ad(srv_is_being_started || | ||
1160 | 121 | !trx_find_descriptor(trx_sys->descriptors, | ||
1161 | 122 | trx_sys->descr_n_used, | ||
1162 | 123 | trx->id)); | ||
1163 | 124 | |||
1164 | 125 | n_used = trx_sys->descr_n_used + 1; | ||
1165 | 126 | n_max = trx_sys->descr_n_max; | ||
1166 | 127 | |||
1167 | 128 | if (UNIV_UNLIKELY(n_used > n_max)) { | ||
1168 | 129 | |||
1169 | 130 | n_max = n_max * 2; | ||
1170 | 131 | |||
1171 | 132 | trx_sys->descriptors = static_cast<trx_id_t*>( | ||
1172 | 133 | ut_realloc(trx_sys->descriptors, | ||
1173 | 134 | n_max * sizeof(trx_id_t))); | ||
1174 | 135 | |||
1175 | 136 | trx_sys->descr_n_max = n_max; | ||
1176 | 137 | } | ||
1177 | 138 | |||
1178 | 139 | descr = trx_sys->descriptors + n_used - 1; | ||
1179 | 140 | |||
1180 | 141 | if (UNIV_UNLIKELY(n_used > 1 && trx->id < descr[-1])) { | ||
1181 | 142 | |||
1182 | 143 | /* Find the slot where it should be inserted. We could use a | ||
1183 | 144 | binary search, but in reality linear search should be faster, | ||
1184 | 145 | because the slot we are looking for is near the array end. */ | ||
1185 | 146 | |||
1186 | 147 | trx_id_t* tdescr; | ||
1187 | 148 | |||
1188 | 149 | for (tdescr = descr - 1; | ||
1189 | 150 | tdescr >= trx_sys->descriptors && *tdescr > trx->id; | ||
1190 | 151 | tdescr--) { | ||
1191 | 152 | } | ||
1192 | 153 | |||
1193 | 154 | tdescr++; | ||
1194 | 155 | |||
1195 | 156 | ut_memmove(tdescr + 1, tdescr, (descr - tdescr) * | ||
1196 | 157 | sizeof(trx_id_t)); | ||
1197 | 158 | |||
1198 | 159 | descr = tdescr; | ||
1199 | 160 | } | ||
1200 | 161 | |||
1201 | 162 | *descr = trx->id; | ||
1202 | 163 | |||
1203 | 164 | trx_sys->descr_n_used = n_used; | ||
1204 | 165 | } | ||
1205 | 166 | |||
1206 | 167 | /*************************************************************//** | ||
1207 | 168 | Release a slot for a given trx in the global descriptors array. */ | ||
1208 | 169 | UNIV_INTERN | ||
1209 | 170 | void | ||
1210 | 171 | trx_release_descriptor( | ||
1211 | 172 | /*===================*/ | ||
1212 | 173 | trx_t* trx) /*!< in: trx pointer */ | ||
1213 | 174 | { | ||
1214 | 175 | ulint size; | ||
1215 | 176 | trx_id_t* descr; | ||
1216 | 177 | |||
1217 | 178 | ut_ad(mutex_own(&trx_sys->mutex)); | ||
1218 | 179 | |||
1219 | 180 | if (UNIV_LIKELY(trx->in_trx_serial_list)) { | ||
1220 | 181 | |||
1221 | 182 | UT_LIST_REMOVE(trx_serial_list, trx_sys->trx_serial_list, | ||
1222 | 183 | trx); | ||
1223 | 184 | trx->in_trx_serial_list = 0; | ||
1224 | 185 | } | ||
1225 | 186 | |||
1226 | 187 | descr = trx_find_descriptor(trx_sys->descriptors, | ||
1227 | 188 | trx_sys->descr_n_used, | ||
1228 | 189 | trx->id); | ||
1229 | 190 | |||
1230 | 191 | if (UNIV_UNLIKELY(descr == NULL)) { | ||
1231 | 192 | |||
1232 | 193 | return; | ||
1233 | 194 | } | ||
1234 | 195 | |||
1235 | 196 | size = (trx_sys->descriptors + trx_sys->descr_n_used - 1 - descr) * | ||
1236 | 197 | sizeof(trx_id_t); | ||
1237 | 198 | |||
1238 | 199 | if (UNIV_LIKELY(size > 0)) { | ||
1239 | 200 | |||
1240 | 201 | ut_memmove(descr, descr + 1, size); | ||
1241 | 202 | } | ||
1242 | 203 | |||
1243 | 204 | trx_sys->descr_n_used--; | ||
1244 | 205 | } | ||
1245 | 206 | |||
1246 | 86 | /****************************************************************//** | 207 | /****************************************************************//** |
1247 | 87 | Creates and initializes a transaction object. It must be explicitly | 208 | Creates and initializes a transaction object. It must be explicitly |
1248 | 88 | started with trx_start_if_not_started() before using it. The default | 209 | started with trx_start_if_not_started() before using it. The default |
1249 | @@ -108,6 +229,7 @@ | |||
1250 | 108 | trx->isolation_level = TRX_ISO_REPEATABLE_READ; | 229 | trx->isolation_level = TRX_ISO_REPEATABLE_READ; |
1251 | 109 | 230 | ||
1252 | 110 | trx->no = IB_ULONGLONG_MAX; | 231 | trx->no = IB_ULONGLONG_MAX; |
1253 | 232 | trx->in_trx_serial_list = 0; | ||
1254 | 111 | 233 | ||
1255 | 112 | trx->support_xa = TRUE; | 234 | trx->support_xa = TRUE; |
1256 | 113 | 235 | ||
1257 | @@ -207,11 +329,12 @@ | |||
1258 | 207 | } | 329 | } |
1259 | 208 | 330 | ||
1260 | 209 | /********************************************************************//** | 331 | /********************************************************************//** |
1262 | 210 | Frees a transaction object. */ | 332 | Frees a transaction object without releasing the corresponding descriptor. |
1263 | 333 | Should be used by callers that already own trx_sys->mutex. */ | ||
1264 | 211 | static | 334 | static |
1265 | 212 | void | 335 | void |
1268 | 213 | trx_free( | 336 | trx_free_low( |
1269 | 214 | /*=====*/ | 337 | /*=========*/ |
1270 | 215 | trx_t* trx) /*!< in, own: trx object */ | 338 | trx_t* trx) /*!< in, own: trx object */ |
1271 | 216 | { | 339 | { |
1272 | 217 | ut_a(trx->magic_n == TRX_MAGIC_N); | 340 | ut_a(trx->magic_n == TRX_MAGIC_N); |
1273 | @@ -255,6 +378,21 @@ | |||
1274 | 255 | } | 378 | } |
1275 | 256 | 379 | ||
1276 | 257 | /********************************************************************//** | 380 | /********************************************************************//** |
1277 | 381 | Frees a transaction object. */ | ||
1278 | 382 | static | ||
1279 | 383 | void | ||
1280 | 384 | trx_free( | ||
1281 | 385 | /*=========*/ | ||
1282 | 386 | trx_t* trx) /*!< in, own: trx object */ | ||
1283 | 387 | { | ||
1284 | 388 | mutex_enter(&trx_sys->mutex); | ||
1285 | 389 | trx_release_descriptor(trx); | ||
1286 | 390 | mutex_exit(&trx_sys->mutex); | ||
1287 | 391 | |||
1288 | 392 | trx_free_low(trx); | ||
1289 | 393 | } | ||
1290 | 394 | |||
1291 | 395 | /********************************************************************//** | ||
1292 | 258 | Frees a transaction object of a background operation of the master thread. */ | 396 | Frees a transaction object of a background operation of the master thread. */ |
1293 | 259 | UNIV_INTERN | 397 | UNIV_INTERN |
1294 | 260 | void | 398 | void |
1295 | @@ -328,7 +466,11 @@ | |||
1296 | 328 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); | 466 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); |
1297 | 329 | ut_d(trx->in_rw_trx_list = FALSE); | 467 | ut_d(trx->in_rw_trx_list = FALSE); |
1298 | 330 | 468 | ||
1300 | 331 | trx_free(trx); | 469 | trx_release_descriptor(trx); |
1301 | 470 | |||
1302 | 471 | trx_free_low(trx); | ||
1303 | 472 | |||
1304 | 473 | ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->rw_trx_list)); | ||
1305 | 332 | } | 474 | } |
1306 | 333 | 475 | ||
1307 | 334 | /********************************************************************//** | 476 | /********************************************************************//** |
1308 | @@ -595,6 +737,7 @@ | |||
1309 | 595 | 737 | ||
1310 | 596 | UT_LIST_INIT(trx_sys->ro_trx_list); | 738 | UT_LIST_INIT(trx_sys->ro_trx_list); |
1311 | 597 | UT_LIST_INIT(trx_sys->rw_trx_list); | 739 | UT_LIST_INIT(trx_sys->rw_trx_list); |
1312 | 740 | UT_LIST_INIT(trx_sys->trx_serial_list); | ||
1313 | 598 | 741 | ||
1314 | 599 | /* Look from the rollback segments if there exist undo logs for | 742 | /* Look from the rollback segments if there exist undo logs for |
1315 | 600 | transactions */ | 743 | transactions */ |
1316 | @@ -617,6 +760,11 @@ | |||
1317 | 617 | 760 | ||
1318 | 618 | trx = trx_resurrect_insert(undo, rseg); | 761 | trx = trx_resurrect_insert(undo, rseg); |
1319 | 619 | 762 | ||
1320 | 763 | if (trx->state == TRX_STATE_ACTIVE || | ||
1321 | 764 | trx->state == TRX_STATE_PREPARED) { | ||
1322 | 765 | |||
1323 | 766 | trx_reserve_descriptor(trx); | ||
1324 | 767 | } | ||
1325 | 620 | trx_list_rw_insert_ordered(trx); | 768 | trx_list_rw_insert_ordered(trx); |
1326 | 621 | } | 769 | } |
1327 | 622 | 770 | ||
1328 | @@ -642,6 +790,11 @@ | |||
1329 | 642 | trx_resurrect_update(trx, undo, rseg); | 790 | trx_resurrect_update(trx, undo, rseg); |
1330 | 643 | 791 | ||
1331 | 644 | if (trx_created) { | 792 | if (trx_created) { |
1332 | 793 | if (trx->state == TRX_STATE_ACTIVE || | ||
1333 | 794 | trx->state == TRX_STATE_PREPARED) { | ||
1334 | 795 | |||
1335 | 796 | trx_reserve_descriptor(trx); | ||
1336 | 797 | } | ||
1337 | 645 | trx_list_rw_insert_ordered(trx); | 798 | trx_list_rw_insert_ordered(trx); |
1338 | 646 | } | 799 | } |
1339 | 647 | } | 800 | } |
1340 | @@ -791,6 +944,8 @@ | |||
1341 | 791 | UT_LIST_ADD_FIRST(trx_list, trx_sys->rw_trx_list, trx); | 944 | UT_LIST_ADD_FIRST(trx_list, trx_sys->rw_trx_list, trx); |
1342 | 792 | ut_d(trx->in_rw_trx_list = TRUE); | 945 | ut_d(trx->in_rw_trx_list = TRUE); |
1343 | 793 | ut_d(trx_sys->rw_max_trx_id = trx->id); | 946 | ut_d(trx_sys->rw_max_trx_id = trx->id); |
1344 | 947 | |||
1345 | 948 | trx_reserve_descriptor(trx); | ||
1346 | 794 | } | 949 | } |
1347 | 795 | 950 | ||
1348 | 796 | ut_ad(trx_sys_validate_trx_list()); | 951 | ut_ad(trx_sys_validate_trx_list()); |
1349 | @@ -820,6 +975,14 @@ | |||
1350 | 820 | 975 | ||
1351 | 821 | trx->no = trx_sys_get_new_trx_id(); | 976 | trx->no = trx_sys_get_new_trx_id(); |
1352 | 822 | 977 | ||
1353 | 978 | if (UNIV_LIKELY(trx->in_trx_serial_list == 0)) { | ||
1354 | 979 | |||
1355 | 980 | UT_LIST_ADD_LAST(trx_serial_list, trx_sys->trx_serial_list, | ||
1356 | 981 | trx); | ||
1357 | 982 | |||
1358 | 983 | trx->in_trx_serial_list = 1; | ||
1359 | 984 | } | ||
1360 | 985 | |||
1361 | 823 | /* If the rollack segment is not empty then the | 986 | /* If the rollack segment is not empty then the |
1362 | 824 | new trx_t::no can't be less than any trx_t::no | 987 | new trx_t::no can't be less than any trx_t::no |
1363 | 825 | already in the rollback segment. User threads only | 988 | already in the rollback segment. User threads only |
1364 | @@ -1104,6 +1267,8 @@ | |||
1365 | 1104 | } else { | 1267 | } else { |
1366 | 1105 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); | 1268 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); |
1367 | 1106 | ut_d(trx->in_rw_trx_list = FALSE); | 1269 | ut_d(trx->in_rw_trx_list = FALSE); |
1368 | 1270 | ut_ad(trx_sys->descr_n_used <= | ||
1369 | 1271 | UT_LIST_GET_LEN(trx_sys->rw_trx_list)); | ||
1370 | 1107 | MONITOR_INC(MONITOR_TRX_RW_COMMIT); | 1272 | MONITOR_INC(MONITOR_TRX_RW_COMMIT); |
1371 | 1108 | } | 1273 | } |
1372 | 1109 | 1274 | ||
1373 | @@ -1220,6 +1385,8 @@ | |||
1374 | 1220 | 1385 | ||
1375 | 1221 | trx->dict_operation = TRX_DICT_OP_NONE; | 1386 | trx->dict_operation = TRX_DICT_OP_NONE; |
1376 | 1222 | 1387 | ||
1377 | 1388 | ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->rw_trx_list)); | ||
1378 | 1389 | |||
1379 | 1223 | trx->error_state = DB_SUCCESS; | 1390 | trx->error_state = DB_SUCCESS; |
1380 | 1224 | 1391 | ||
1381 | 1225 | /* trx->in_mysql_trx_list would hold between | 1392 | /* trx->in_mysql_trx_list would hold between |
1382 | @@ -1343,10 +1510,14 @@ | |||
1383 | 1343 | ut_a(!trx->read_only); | 1510 | ut_a(!trx->read_only); |
1384 | 1344 | 1511 | ||
1385 | 1345 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); | 1512 | UT_LIST_REMOVE(trx_list, trx_sys->rw_trx_list, trx); |
1386 | 1513 | ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->rw_trx_list)); | ||
1387 | 1346 | 1514 | ||
1388 | 1347 | assert_trx_in_rw_list(trx); | 1515 | assert_trx_in_rw_list(trx); |
1389 | 1348 | ut_d(trx->in_rw_trx_list = FALSE); | 1516 | ut_d(trx->in_rw_trx_list = FALSE); |
1390 | 1349 | 1517 | ||
1391 | 1518 | trx->state = TRX_STATE_NOT_STARTED; | ||
1392 | 1519 | trx_release_descriptor(trx); | ||
1393 | 1520 | |||
1394 | 1350 | mutex_exit(&trx_sys->mutex); | 1521 | mutex_exit(&trx_sys->mutex); |
1395 | 1351 | 1522 | ||
1396 | 1352 | /* Change the transaction state without mutex protection, now | 1523 | /* Change the transaction state without mutex protection, now |
1397 | @@ -1356,7 +1527,6 @@ | |||
1398 | 1356 | ut_ad(!trx->in_ro_trx_list); | 1527 | ut_ad(!trx->in_ro_trx_list); |
1399 | 1357 | ut_ad(!trx->in_rw_trx_list); | 1528 | ut_ad(!trx->in_rw_trx_list); |
1400 | 1358 | ut_ad(!trx->in_mysql_trx_list); | 1529 | ut_ad(!trx->in_mysql_trx_list); |
1401 | 1359 | trx->state = TRX_STATE_NOT_STARTED; | ||
1402 | 1360 | } | 1530 | } |
1403 | 1361 | 1531 | ||
1404 | 1362 | /********************************************************************//** | 1532 | /********************************************************************//** |
1405 | @@ -1376,11 +1546,8 @@ | |||
1406 | 1376 | return(trx->read_view); | 1546 | return(trx->read_view); |
1407 | 1377 | } | 1547 | } |
1408 | 1378 | 1548 | ||
1414 | 1379 | if (!trx->read_view) { | 1549 | trx->read_view = read_view_open_now(trx->id, trx->prebuilt_view); |
1415 | 1380 | trx->read_view = read_view_open_now(trx->id, | 1550 | trx->global_read_view = trx->read_view; |
1411 | 1381 | trx->prebuilt_view); | ||
1412 | 1382 | trx->global_read_view = trx->read_view; | ||
1413 | 1383 | } | ||
1416 | 1384 | 1551 | ||
1417 | 1385 | return(trx->read_view); | 1552 | return(trx->read_view); |
1418 | 1386 | } | 1553 | } |
1419 | 1387 | 1554 | ||
1420 | === added directory 'policy' | |||
1421 | === added directory 'policy/apparmor' | |||
1422 | === added file 'policy/apparmor/usr.sbin.mysqld' | |||
1423 | --- policy/apparmor/usr.sbin.mysqld 1970-01-01 00:00:00 +0000 | |||
1424 | +++ policy/apparmor/usr.sbin.mysqld 2013-05-24 12:02:59 +0000 | |||
1425 | @@ -0,0 +1,61 @@ | |||
1426 | 1 | # Last Modified: Thu Mar 7 21:58:51 2013 | ||
1427 | 2 | # Based on usr.sbin.mysqld packaged in mysql-server in Ubuntu. | ||
1428 | 3 | # For Percona Server and Percona XtraDB Cluster | ||
1429 | 4 | |||
1430 | 5 | #include <tunables/global> | ||
1431 | 6 | |||
1432 | 7 | /usr/sbin/mysqld flags=(complain) { | ||
1433 | 8 | #include <abstractions/base> | ||
1434 | 9 | #include <abstractions/mysql> | ||
1435 | 10 | #include <abstractions/nameservice> | ||
1436 | 11 | #include <abstractions/user-tmp> | ||
1437 | 12 | #include <abstractions/winbind> | ||
1438 | 13 | #include <local/usr.sbin.mysqld> | ||
1439 | 14 | |||
1440 | 15 | |||
1441 | 16 | capability chown, | ||
1442 | 17 | capability dac_override, | ||
1443 | 18 | capability setgid, | ||
1444 | 19 | capability setuid, | ||
1445 | 20 | capability sys_rawio, | ||
1446 | 21 | capability sys_resource, | ||
1447 | 22 | |||
1448 | 23 | network tcp, | ||
1449 | 24 | |||
1450 | 25 | |||
1451 | 26 | /dev/dm-0 r, | ||
1452 | 27 | /etc/group r, | ||
1453 | 28 | /etc/gai.conf r, | ||
1454 | 29 | /etc/hosts.allow r, | ||
1455 | 30 | /etc/hosts.deny r, | ||
1456 | 31 | /etc/ld.so.cache r, | ||
1457 | 32 | /etc/mtab r, | ||
1458 | 33 | /etc/my.cnf r, | ||
1459 | 34 | /etc/mysql/*.cnf r, | ||
1460 | 35 | /etc/mysql/*.pem r, | ||
1461 | 36 | /etc/mysql/conf.d/ r, | ||
1462 | 37 | /etc/mysql/conf.d/* r, | ||
1463 | 38 | /etc/nsswitch.conf r, | ||
1464 | 39 | /etc/passwd r, | ||
1465 | 40 | /etc/services r, | ||
1466 | 41 | /run/mysqld/mysqld.pid w, | ||
1467 | 42 | /run/mysqld/mysqld.sock w, | ||
1468 | 43 | /sys/devices/system/cpu/ r, | ||
1469 | 44 | owner /tmp/** lk, | ||
1470 | 45 | /tmp/** rw, | ||
1471 | 46 | /usr/lib/mysql/plugin/ r, | ||
1472 | 47 | /usr/lib/mysql/plugin/*.so* mr, | ||
1473 | 48 | /usr/sbin/mysqld mr, | ||
1474 | 49 | /usr/share/mysql/** r, | ||
1475 | 50 | /var/lib/mysql/ r, | ||
1476 | 51 | /var/lib/mysql/** rwk, | ||
1477 | 52 | /var/log/mysql.err rw, | ||
1478 | 53 | /var/log/mysql.log rw, | ||
1479 | 54 | /var/log/mysql/ r, | ||
1480 | 55 | /var/log/mysql/* rw, | ||
1481 | 56 | /var/run/mysqld/mysqld.pid w, | ||
1482 | 57 | /var/run/mysqld/mysqld.sock w, | ||
1483 | 58 | |||
1484 | 59 | # Site-specific additions and overrides. See local/README for details. | ||
1485 | 60 | #include <local/usr.sbin.mysqld> | ||
1486 | 61 | } | ||
1487 | 0 | 62 | ||
1488 | === added file 'policy/apparmor/usr.sbin.mysqld.local' | |||
1489 | --- policy/apparmor/usr.sbin.mysqld.local 1970-01-01 00:00:00 +0000 | |||
1490 | +++ policy/apparmor/usr.sbin.mysqld.local 2013-05-24 12:02:59 +0000 | |||
1491 | @@ -0,0 +1,2 @@ | |||
1492 | 1 | # Site-specific additions and overrides for usr.sbin.mysqld.. | ||
1493 | 2 | # For more details, please see /etc/apparmor.d/local/README. | ||
1494 | 0 | 3 | ||
1495 | === added directory 'policy/selinux' | |||
1496 | === added file 'policy/selinux/percona-server.fc' | |||
1497 | --- policy/selinux/percona-server.fc 1970-01-01 00:00:00 +0000 | |||
1498 | +++ policy/selinux/percona-server.fc 2013-05-24 12:02:59 +0000 | |||
1499 | @@ -0,0 +1,6 @@ | |||
1500 | 1 | /etc/init\.d/rc\.d/mysql -- gen_context(system_u:object_r:mysqld_initrc_exec_t,s0) | ||
1501 | 2 | /var/lib/mysql/.*\.log -- gen_context(system_u:object_r:mysqld_log_t,s0) | ||
1502 | 3 | /var/lib/mysql/.*\.err -- gen_context(system_u:object_r:mysqld_log_t,s0) | ||
1503 | 4 | /var/lib/mysql/.*\.pid -- gen_context(system_u:object_r:mysqld_var_run_t,s0) | ||
1504 | 5 | /var/lib/mysql/.*\.cnf -- gen_context(system_u:object_r:mysqld_etc_t,s0) | ||
1505 | 6 | /usr/bin/xtrabackup.* -- gen_context(system_u:object_r:mysqld_exec_t,s0) | ||
1506 | 0 | 7 | ||
1507 | === added file 'policy/selinux/percona-server.te' | |||
1508 | --- policy/selinux/percona-server.te 1970-01-01 00:00:00 +0000 | |||
1509 | +++ policy/selinux/percona-server.te 2013-05-24 12:02:59 +0000 | |||
1510 | @@ -0,0 +1,35 @@ | |||
1511 | 1 | # This adds few more rules in addition to mysql.pp in selinux-policy-targeted | ||
1512 | 2 | module percona-server 1.0; | ||
1513 | 3 | |||
1514 | 4 | require { | ||
1515 | 5 | type user_tmp_t; | ||
1516 | 6 | type mysqld_safe_t; | ||
1517 | 7 | type tmp_t; | ||
1518 | 8 | type fixed_disk_device_t; | ||
1519 | 9 | type mysqld_t; | ||
1520 | 10 | type tmpfs_t; | ||
1521 | 11 | class sock_file { getattr unlink create }; | ||
1522 | 12 | class capability { sys_nice sys_resource }; | ||
1523 | 13 | class blk_file { read write open }; | ||
1524 | 14 | class file { write getattr read create unlink open }; | ||
1525 | 15 | class dir { search read write remove_name open add_name }; | ||
1526 | 16 | } | ||
1527 | 17 | |||
1528 | 18 | #============= mysqld_safe_t ============== | ||
1529 | 19 | allow mysqld_safe_t self:capability { sys_nice sys_resource }; | ||
1530 | 20 | |||
1531 | 21 | allow mysqld_safe_t tmp_t:dir { write remove_name }; | ||
1532 | 22 | allow mysqld_safe_t tmp_t:sock_file { getattr unlink }; | ||
1533 | 23 | allow mysqld_safe_t user_tmp_t:sock_file { getattr unlink }; | ||
1534 | 24 | |||
1535 | 25 | #============= mysqld_t ============== | ||
1536 | 26 | allow mysqld_t fixed_disk_device_t:blk_file { read write open }; | ||
1537 | 27 | allow mysqld_t tmp_t:sock_file { create unlink }; | ||
1538 | 28 | |||
1539 | 29 | allow mysqld_t tmpfs_t:dir { write search read remove_name open add_name }; | ||
1540 | 30 | allow mysqld_t tmpfs_t:file { write getattr read create unlink open }; | ||
1541 | 31 | |||
1542 | 32 | allow mysqld_t user_tmp_t:dir { write add_name }; | ||
1543 | 33 | allow mysqld_t user_tmp_t:file create; | ||
1544 | 34 | |||
1545 | 35 | allow mysqld_t tmp_t:file { append create read write open getattr unlink setattr }; |
- The patch would be OK, but I did find one issue which IMHO is_active_ low is a returning function that returns NULL in one of the code
requires recommitting (although the test cycle could be
skipped) or follow-up addressing (I don't have a strong opinion
on recomitting vs follow-up): trx_rw_
bool-
paths.
- If we are recommitting, then in_trx_serial_list should be bool,
not ibool as well, and true/false used instead of 0/1 for
setting it, spurious newline at diff line 278. The row0sel.cc
change is spurious as well?
Random remark:
- trx_descr_cmp() should be defined in trx0trx.ic, not .c? So search( ) in the brave new
then compiler can resolve the function pointer to inlining. It
is also possible to use std::binary_
C++ world.
Last and least absolutely random remarks:
- I don't fully understand the header comment for rw_get_ active_ trx_by_ id() stating that the returned pointer state_eq( )? I see that all callers hold the sys->mutex, thus it does not seem to be a real issue
trx_
must not be dereferenced unless lock_sys->mutex is held. But
the function itself dereferences the pointer in
trx_
lock_
though.
- Upstream started making heavy use of __attribute__ function
annotations to cause extra warnings on misuse, especially
nonnull, warn_unused_result. Maybe not bad idea for us well
where it applies.