~percona-dev/percona-xtradb/fix-bug-405714

« back to all changes in this revision

Viewing changes to innodb_1.0.3_fix_for_5.0.36.patch

  • Committer: kinoyasu
  • Date: 2009-07-22 07:11:37 UTC
  • mfrom: (87.1.1 fix-bug39320)
  • Revision ID: kinoyasu@gauntlet3-20090722071137-xtplxg7syjyc16w0
bug fix http://bugs.mysql.com/39320

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
diff -ru innodb_plugin-1.0.3_orig/dict/dict0dict.c innodb_plugin-1.0.3_tmp/dict/dict0dict.c
2
 
--- innodb_plugin-1.0.3_orig/dict/dict0dict.c   2009-07-14 13:51:44.000000000 +0900
3
 
+++ innodb_plugin-1.0.3_tmp/dict/dict0dict.c    2009-07-14 16:34:58.000000000 +0900
 
2
--- innodb_plugin-1.0.3_orig/dict/dict0dict.c   2009-07-21 15:19:42.000000000 +0900
 
3
+++ innodb_plugin-1.0.3_tmp/dict/dict0dict.c    2009-07-21 15:20:32.000000000 +0900
4
4
@@ -3049,7 +3049,7 @@
5
5
                } else if (quote) {
6
6
                        /* Within quotes: do not look for
11
11
                        quote = *sptr;
12
12
                } else if (*sptr == '#'
13
13
diff -ru innodb_plugin-1.0.3_orig/handler/ha_innodb.cc innodb_plugin-1.0.3_tmp/handler/ha_innodb.cc
14
 
--- innodb_plugin-1.0.3_orig/handler/ha_innodb.cc       2009-07-14 13:51:44.000000000 +0900
15
 
+++ innodb_plugin-1.0.3_tmp/handler/ha_innodb.cc        2009-07-14 14:46:54.000000000 +0900
 
14
--- innodb_plugin-1.0.3_orig/handler/ha_innodb.cc       2009-07-21 15:19:42.000000000 +0900
 
15
+++ innodb_plugin-1.0.3_tmp/handler/ha_innodb.cc        2009-07-21 15:20:32.000000000 +0900
16
16
@@ -9319,7 +9319,8 @@
17
17
 
18
18
        /* Check that row format didn't change */
23
23
 
24
24
                return(COMPATIBLE_DATA_NO);
25
25
        }
 
26
diff -ru innodb_plugin-1.0.3_orig/include/row0mysql.h innodb_plugin-1.0.3_tmp/include/row0mysql.h
 
27
--- innodb_plugin-1.0.3_orig/include/row0mysql.h        2009-02-17 18:33:38.000000000 +0900
 
28
+++ innodb_plugin-1.0.3_tmp/include/row0mysql.h 2009-07-21 15:22:19.000000000 +0900
 
29
@@ -695,6 +695,21 @@
 
30
                                        This eliminates lock waits in some
 
31
                                        cases; note that this breaks
 
32
                                        serializability. */
 
33
+       ulint           new_rec_locks;  /* normally 0; if
 
34
+                                       srv_locks_unsafe_for_binlog is
 
35
+                                       TRUE or session is using READ
 
36
+                                       COMMITTED isolation level, in a
 
37
+                                       cursor search, if we set a new
 
38
+                                       record lock on an index, this is
 
39
+                                       incremented; this is used in
 
40
+                                       releasing the locks under the
 
41
+                                       cursors if we are performing an
 
42
+                                       UPDATE and we determine after
 
43
+                                       retrieving the row that it does
 
44
+                                       not need to be locked; thus,
 
45
+                                       these can be used to implement a
 
46
+                                       'mini-rollback' that releases
 
47
+                                       the latest record locks */
 
48
        ulint           mysql_prefix_len;/* byte offset of the end of
 
49
                                        the last requested column */
 
50
        ulint           mysql_row_len;  /* length in bytes of a row in the
 
51
diff -ru innodb_plugin-1.0.3_orig/include/trx0trx.h innodb_plugin-1.0.3_tmp/include/trx0trx.h
 
52
--- innodb_plugin-1.0.3_orig/include/trx0trx.h  2009-07-21 15:19:42.000000000 +0900
 
53
+++ innodb_plugin-1.0.3_tmp/include/trx0trx.h   2009-07-21 15:23:51.000000000 +0900
 
54
@@ -43,34 +43,6 @@
 
55
 the kernel mutex */
 
56
 extern ulint   trx_n_mysql_transactions;
 
57
 
 
58
-/*****************************************************************
 
59
-Resets the new record lock info in a transaction struct. */
 
60
-UNIV_INLINE
 
61
-void
 
62
-trx_reset_new_rec_lock_info(
 
63
-/*========================*/
 
64
-       trx_t*  trx);   /* in: transaction struct */
 
65
-/*****************************************************************
 
66
-Registers that we have set a new record lock on an index. We only have space
 
67
-to store 2 indexes! If this is called to store more than 2 indexes after
 
68
-trx_reset_new_rec_lock_info(), then this function does nothing. */
 
69
-UNIV_INLINE
 
70
-void
 
71
-trx_register_new_rec_lock(
 
72
-/*======================*/
 
73
-       trx_t*          trx,    /* in: transaction struct */
 
74
-       dict_index_t*   index); /* in: trx sets a new record lock on this
 
75
-                               index */
 
76
-/*****************************************************************
 
77
-Checks if trx has set a new record lock on an index. */
 
78
-UNIV_INLINE
 
79
-ibool
 
80
-trx_new_rec_locks_contain(
 
81
-/*======================*/
 
82
-                               /* out: TRUE if trx has set a new record lock
 
83
-                               on index */
 
84
-       trx_t*          trx,    /* in: transaction struct */
 
85
-       dict_index_t*   index); /* in: index */
 
86
 /************************************************************************
 
87
 Releases the search latch if trx has reserved it. */
 
88
 UNIV_INTERN
 
89
@@ -624,20 +596,6 @@
 
90
                                        to srv_conc_innodb_enter, if the value
 
91
                                        here is > 0, we decrement this by 1 */
 
92
        /*------------------------------*/
 
93
-       dict_index_t*   new_rec_locks[2];/* these are normally NULL; if
 
94
-                                       srv_locks_unsafe_for_binlog is TRUE
 
95
-                                       or session is using READ COMMITTED
 
96
-                                       isolation level,
 
97
-                                       in a cursor search, if we set a new
 
98
-                                       record lock on an index, this is set
 
99
-                                       to point to the index; this is
 
100
-                                       used in releasing the locks under the
 
101
-                                       cursors if we are performing an UPDATE
 
102
-                                       and we determine after retrieving
 
103
-                                       the row that it does not need to be
 
104
-                                       locked; thus, these can be used to
 
105
-                                       implement a 'mini-rollback' that
 
106
-                                       releases the latest record locks */
 
107
        UT_LIST_NODE_T(trx_t)
 
108
                        trx_list;       /* list of transactions */
 
109
        UT_LIST_NODE_T(trx_t)
 
110
diff -ru innodb_plugin-1.0.3_orig/include/trx0trx.ic innodb_plugin-1.0.3_tmp/include/trx0trx.ic
 
111
--- innodb_plugin-1.0.3_orig/include/trx0trx.ic 2009-02-17 18:43:50.000000000 +0900
 
112
+++ innodb_plugin-1.0.3_tmp/include/trx0trx.ic  2009-07-21 15:25:30.000000000 +0900
 
113
@@ -55,64 +55,6 @@
 
114
        }
 
115
 }
 
116
 
 
117
-/*****************************************************************
 
118
-Resets the new record lock info in a transaction struct. */
 
119
-UNIV_INLINE
 
120
-void
 
121
-trx_reset_new_rec_lock_info(
 
122
-/*========================*/
 
123
-       trx_t*  trx)    /* in: transaction struct */
 
124
-{
 
125
-       trx->new_rec_locks[0] = NULL;
 
126
-       trx->new_rec_locks[1] = NULL;
 
127
-}
 
128
-
 
129
-/*****************************************************************
 
130
-Registers that we have set a new record lock on an index. We only have space
 
131
-to store 2 indexes! If this is called to store more than 2 indexes after
 
132
-trx_reset_new_rec_lock_info(), then this function does nothing. */
 
133
-UNIV_INLINE
 
134
-void
 
135
-trx_register_new_rec_lock(
 
136
-/*======================*/
 
137
-       trx_t*          trx,    /* in: transaction struct */
 
138
-       dict_index_t*   index)  /* in: trx sets a new record lock on this
 
139
-                               index */
 
140
-{
 
141
-       if (trx->new_rec_locks[0] == NULL) {
 
142
-               trx->new_rec_locks[0] = index;
 
143
-
 
144
-               return;
 
145
-       }
 
146
-
 
147
-       if (trx->new_rec_locks[0] == index) {
 
148
-
 
149
-               return;
 
150
-       }
 
151
-
 
152
-       if (trx->new_rec_locks[1] != NULL) {
 
153
-
 
154
-               return;
 
155
-       }
 
156
-
 
157
-       trx->new_rec_locks[1] = index;
 
158
-}
 
159
-
 
160
-/*****************************************************************
 
161
-Checks if trx has set a new record lock on an index. */
 
162
-UNIV_INLINE
 
163
-ibool
 
164
-trx_new_rec_locks_contain(
 
165
-/*======================*/
 
166
-                               /* out: TRUE if trx has set a new record lock
 
167
-                               on index */
 
168
-       trx_t*          trx,    /* in: transaction struct */
 
169
-       dict_index_t*   index)  /* in: index */
 
170
-{
 
171
-       return(trx->new_rec_locks[0] == index
 
172
-              || trx->new_rec_locks[1] == index);
 
173
-}
 
174
-
 
175
 /********************************************************************
 
176
 Retrieves the error_info field from a trx. */
 
177
 UNIV_INLINE
 
178
diff -ru innodb_plugin-1.0.3_orig/lock/lock0lock.c innodb_plugin-1.0.3_tmp/lock/lock0lock.c
 
179
--- innodb_plugin-1.0.3_orig/lock/lock0lock.c   2009-07-21 15:19:42.000000000 +0900
 
180
+++ innodb_plugin-1.0.3_tmp/lock/lock0lock.c    2009-07-21 15:27:20.000000000 +0900
 
181
@@ -1976,12 +1976,6 @@
 
182
        if (lock == NULL) {
 
183
                if (!impl) {
 
184
                        lock_rec_create(mode, block, heap_no, index, trx);
 
185
-
 
186
-                       if (srv_locks_unsafe_for_binlog
 
187
-                           || trx->isolation_level
 
188
-                           == TRX_ISO_READ_COMMITTED) {
 
189
-                               trx_register_new_rec_lock(trx, index);
 
190
-                       }
 
191
                }
 
192
 
 
193
                return(TRUE);
 
194
@@ -2005,11 +1999,6 @@
 
195
 
 
196
                if (!lock_rec_get_nth_bit(lock, heap_no)) {
 
197
                        lock_rec_set_nth_bit(lock, heap_no);
 
198
-                       if (srv_locks_unsafe_for_binlog
 
199
-                           || trx->isolation_level
 
200
-                           == TRX_ISO_READ_COMMITTED) {
 
201
-                               trx_register_new_rec_lock(trx, index);
 
202
-                       }
 
203
                }
 
204
        }
 
205
 
 
206
@@ -2069,22 +2058,12 @@
 
207
 
 
208
                err = lock_rec_enqueue_waiting(mode, block, heap_no,
 
209
                                               index, thr);
 
210
-
 
211
-               if (srv_locks_unsafe_for_binlog
 
212
-                   || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
 
213
-                       trx_register_new_rec_lock(trx, index);
 
214
-               }
 
215
        } else {
 
216
                if (!impl) {
 
217
                        /* Set the requested lock on the record */
 
218
 
 
219
                        lock_rec_add_to_queue(LOCK_REC | mode, block,
 
220
                                              heap_no, index, trx);
 
221
-                       if (srv_locks_unsafe_for_binlog
 
222
-                           || trx->isolation_level
 
223
-                           == TRX_ISO_READ_COMMITTED) {
 
224
-                               trx_register_new_rec_lock(trx, index);
 
225
-                       }
 
226
                }
 
227
 
 
228
                err = DB_SUCCESS;
 
229
diff -ru innodb_plugin-1.0.3_orig/row/row0mysql.c innodb_plugin-1.0.3_tmp/row/row0mysql.c
 
230
--- innodb_plugin-1.0.3_orig/row/row0mysql.c    2009-07-21 15:19:42.000000000 +0900
 
231
+++ innodb_plugin-1.0.3_tmp/row/row0mysql.c     2009-07-21 16:07:45.000000000 +0900
 
232
@@ -1452,12 +1452,9 @@
 
233
                                        and clust_pcur, and we do not need to
 
234
                                        reposition the cursors. */
 
235
 {
 
236
-       dict_index_t*   index;
 
237
        btr_pcur_t*     pcur            = prebuilt->pcur;
 
238
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
 
239
        trx_t*          trx             = prebuilt->trx;
 
240
-       rec_t*          rec;
 
241
-       mtr_t           mtr;
 
242
 
 
243
        ut_ad(prebuilt && trx);
 
244
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
 
245
@@ -1477,9 +1474,12 @@
 
246
 
 
247
        trx->op_info = "unlock_row";
 
248
 
 
249
-       index = btr_pcur_get_btr_cur(pcur)->index;
 
250
+       if (prebuilt->new_rec_locks >= 1) {
 
251
 
 
252
-       if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
 
253
+               rec_t*          rec;
 
254
+               dict_index_t*   index;
 
255
+               dulint          rec_trx_id;
 
256
+               mtr_t           mtr;
 
257
 
 
258
                mtr_start(&mtr);
 
259
 
 
260
@@ -1490,45 +1490,65 @@
 
261
                }
 
262
 
 
263
                rec = btr_pcur_get_rec(pcur);
 
264
+               index = btr_pcur_get_btr_cur(pcur)->index;
 
265
+
 
266
+               if (prebuilt->new_rec_locks >= 2) {
 
267
+                       /* Restore the cursor position and find the record
 
268
+                       in the clustered index. */
 
269
+
 
270
+                       if (!has_latches_on_recs) {
 
271
+                               btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
272
+                                                         clust_pcur, &mtr);
 
273
+                       }
 
274
 
 
275
-               lock_rec_unlock(trx, btr_pcur_get_block(pcur),
 
276
-                               rec, prebuilt->select_lock_type);
 
277
+                       rec = btr_pcur_get_rec(clust_pcur);
 
278
+                       index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
279
+               }
 
280
 
 
281
-               mtr_commit(&mtr);
 
282
+               /* If the record has been modified by this
 
283
+               transaction, do not unlock it. */
 
284
+               ut_a(dict_index_is_clust(index));
 
285
 
 
286
-               /* If the search was done through the clustered index, then
 
287
-               we have not used clust_pcur at all, and we must NOT try to
 
288
-               reset locks on clust_pcur. The values in clust_pcur may be
 
289
-               garbage! */
 
290
+               if (index->trx_id_offset) {
 
291
+                       rec_trx_id = trx_read_trx_id(rec
 
292
+                                                    + index->trx_id_offset);
 
293
+               } else {
 
294
+                       mem_heap_t*     heap                    = NULL;
 
295
+                       ulint   offsets_[REC_OFFS_NORMAL_SIZE];
 
296
+                       ulint*  offsets                         = offsets_;
 
297
+
 
298
+                       *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
299
+                       offsets = rec_get_offsets(rec, index, offsets,
 
300
+                                                 ULINT_UNDEFINED, &heap);
 
301
 
 
302
-               if (dict_index_is_clust(index)) {
 
303
+                       rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
 
304
 
 
305
-                       goto func_exit;
 
306
+                       if (UNIV_LIKELY_NULL(heap)) {
 
307
+                               mem_heap_free(heap);
 
308
+                       }
 
309
                }
 
310
-       }
 
311
 
 
312
-       index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
313
+               if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
 
314
+                       /* We did not update the record: unlock it */
 
315
 
 
316
-       if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
 
317
+                       rec = btr_pcur_get_rec(pcur);
 
318
+                       index = btr_pcur_get_btr_cur(pcur)->index;
 
319
 
 
320
-               mtr_start(&mtr);
 
321
+                       lock_rec_unlock(trx, btr_pcur_get_block(pcur),
 
322
+                                       rec, prebuilt->select_lock_type);
 
323
 
 
324
-               /* Restore the cursor position and find the record */
 
325
+                       if (prebuilt->new_rec_locks >= 2) {
 
326
+                               rec = btr_pcur_get_rec(clust_pcur);
 
327
+                               index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
328
 
 
329
-               if (!has_latches_on_recs) {
 
330
-                       btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
 
331
-                                                 &mtr);
 
332
+                               lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
 
333
+                                               rec, prebuilt->select_lock_type);
 
334
+                       }
 
335
                }
 
336
 
 
337
-               rec = btr_pcur_get_rec(clust_pcur);
 
338
-
 
339
-               lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
 
340
-                               rec, prebuilt->select_lock_type);
 
341
-
 
342
                mtr_commit(&mtr);
 
343
        }
 
344
 
 
345
-func_exit:
 
346
        trx->op_info = "";
 
347
 
 
348
        return(DB_SUCCESS);
 
349
diff -ru innodb_plugin-1.0.3_orig/row/row0sel.c innodb_plugin-1.0.3_tmp/row/row0sel.c
 
350
--- innodb_plugin-1.0.3_orig/row/row0sel.c      2009-02-17 16:56:33.000000000 +0900
 
351
+++ innodb_plugin-1.0.3_tmp/row/row0sel.c       2009-07-21 16:16:16.000000000 +0900
 
352
@@ -3002,8 +3002,9 @@
 
353
 func_exit:
 
354
        *out_rec = clust_rec;
 
355
 
 
356
-       if (prebuilt->select_lock_type == LOCK_X) {
 
357
-               /* We may use the cursor in update: store its position */
 
358
+       if (prebuilt->select_lock_type != LOCK_NONE) {
 
359
+               /* We may use the cursor in update or in unlock_row():
 
360
+               store its position */
 
361
 
 
362
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
 
363
        }
 
364
@@ -3405,13 +3406,7 @@
 
365
        is set or session is using a READ COMMITED isolation level. Then
 
366
        we are able to remove the record locks set here on an individual
 
367
        row. */
 
368
-
 
369
-       if ((srv_locks_unsafe_for_binlog
 
370
-            || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
371
-           && prebuilt->select_lock_type != LOCK_NONE) {
 
372
-
 
373
-               trx_reset_new_rec_lock_info(trx);
 
374
-       }
 
375
+       prebuilt->new_rec_locks = 0;
 
376
 
 
377
        /*-------------------------------------------------------------*/
 
378
        /* PHASE 1: Try to pop the row from the prefetch cache */
 
379
@@ -4056,6 +4051,12 @@
 
380
                switch (err) {
 
381
                        const rec_t*    old_vers;
 
382
                case DB_SUCCESS:
 
383
+                       if (srv_locks_unsafe_for_binlog
 
384
+                           || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
 
385
+                               /* Note that a record of
 
386
+                               prebuilt->index was locked. */
 
387
+                               prebuilt->new_rec_locks = 1;
 
388
+                       }
 
389
                        break;
 
390
                case DB_LOCK_WAIT:
 
391
                        if (UNIV_LIKELY(prebuilt->row_read_type
 
392
@@ -4086,7 +4087,7 @@
 
393
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
 
394
                                lock_cancel_waiting_and_release(
 
395
                                        trx->wait_lock);
 
396
-                               trx_reset_new_rec_lock_info(trx);
 
397
+                               prebuilt->new_rec_locks = 0;
 
398
                        } else {
 
399
                                mutex_exit(&kernel_mutex);
 
400
 
 
401
@@ -4098,6 +4099,9 @@
 
402
                                                          ULINT_UNDEFINED,
 
403
                                                          &heap);
 
404
                                err = DB_SUCCESS;
 
405
+                               /* Note that a record of
 
406
+                               prebuilt->index was locked. */
 
407
+                               prebuilt->new_rec_locks = 1;
 
408
                                break;
 
409
                        }
 
410
                        mutex_exit(&kernel_mutex);
 
411
@@ -4246,6 +4250,15 @@
 
412
                        goto next_rec;
 
413
                }
 
414
 
 
415
+               if ((srv_locks_unsafe_for_binlog
 
416
+                    || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
417
+                   && prebuilt->select_lock_type != LOCK_NONE) {
 
418
+                       /* Note that both the secondary index record
 
419
+                       and the clustered index record were locked. */
 
420
+                       ut_ad(prebuilt->new_rec_locks == 1);
 
421
+                       prebuilt->new_rec_locks = 2;
 
422
+               }
 
423
+
 
424
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
 
425
 
 
426
                        /* The record is delete marked: we can skip it */
 
427
@@ -4375,13 +4388,7 @@
 
428
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
429
        }
 
430
        did_semi_consistent_read = FALSE;
 
431
-
 
432
-       if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
 
433
-                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
434
-           && prebuilt->select_lock_type != LOCK_NONE) {
 
435
-
 
436
-               trx_reset_new_rec_lock_info(trx);
 
437
-       }
 
438
+       prebuilt->new_rec_locks = 0;
 
439
 
 
440
        /*-------------------------------------------------------------*/
 
441
        /* PHASE 5: Move the cursor to the next index record */
 
442
@@ -4487,7 +4494,7 @@
 
443
                        rec_loop we will again try to set a lock, and
 
444
                        new_rec_lock_info in trx will be right at the end. */
 
445
 
 
446
-                       trx_reset_new_rec_lock_info(trx);
 
447
+                       prebuilt->new_rec_locks = 0;
 
448
                }
 
449
 
 
450
                mode = pcur->search_mode;
 
451
diff -ru innodb_plugin-1.0.3_orig/trx/trx0trx.c innodb_plugin-1.0.3_tmp/trx/trx0trx.c
 
452
--- innodb_plugin-1.0.3_orig/trx/trx0trx.c      2009-07-21 15:19:42.000000000 +0900
 
453
+++ innodb_plugin-1.0.3_tmp/trx/trx0trx.c       2009-07-21 16:30:52.000000000 +0900
 
454
@@ -187,8 +187,6 @@
 
455
        trx->autoinc_locks = ib_vector_create(
 
456
                mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4);
 
457
 
 
458
-       trx_reset_new_rec_lock_info(trx);
 
459
-
 
460
        return(trx);
 
461
 }
 
462