24
24
return(COMPATIBLE_DATA_NO);
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
30
This eliminates lock waits in some
31
cases; note that this breaks
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
56
extern ulint trx_n_mysql_transactions;
58
-/*****************************************************************
59
-Resets the new record lock info in a transaction struct. */
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. */
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
76
-/*****************************************************************
77
-Checks if trx has set a new record lock on an index. */
80
-trx_new_rec_locks_contain(
81
-/*======================*/
82
- /* out: TRUE if trx has set a new record lock
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. */
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
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
117
-/*****************************************************************
118
-Resets the new record lock info in a transaction struct. */
121
-trx_reset_new_rec_lock_info(
122
-/*========================*/
123
- trx_t* trx) /* in: transaction struct */
125
- trx->new_rec_locks[0] = NULL;
126
- trx->new_rec_locks[1] = NULL;
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. */
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
141
- if (trx->new_rec_locks[0] == NULL) {
142
- trx->new_rec_locks[0] = index;
147
- if (trx->new_rec_locks[0] == index) {
152
- if (trx->new_rec_locks[1] != NULL) {
157
- trx->new_rec_locks[1] = index;
160
-/*****************************************************************
161
-Checks if trx has set a new record lock on an index. */
164
-trx_new_rec_locks_contain(
165
-/*======================*/
166
- /* out: TRUE if trx has set a new record lock
168
- trx_t* trx, /* in: transaction struct */
169
- dict_index_t* index) /* in: index */
171
- return(trx->new_rec_locks[0] == index
172
- || trx->new_rec_locks[1] == index);
175
/********************************************************************
176
Retrieves the error_info field from a trx. */
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 @@
184
lock_rec_create(mode, block, heap_no, index, trx);
186
- if (srv_locks_unsafe_for_binlog
187
- || trx->isolation_level
188
- == TRX_ISO_READ_COMMITTED) {
189
- trx_register_new_rec_lock(trx, index);
194
@@ -2005,11 +1999,6 @@
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);
206
@@ -2069,22 +2058,12 @@
208
err = lock_rec_enqueue_waiting(mode, block, heap_no,
211
- if (srv_locks_unsafe_for_binlog
212
- || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
213
- trx_register_new_rec_lock(trx, index);
217
/* Set the requested lock on the record */
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);
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. */
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;
243
ut_ad(prebuilt && trx);
244
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
245
@@ -1477,9 +1474,12 @@
247
trx->op_info = "unlock_row";
249
- index = btr_pcur_get_btr_cur(pcur)->index;
250
+ if (prebuilt->new_rec_locks >= 1) {
252
- if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
254
+ dict_index_t* index;
260
@@ -1490,45 +1490,65 @@
263
rec = btr_pcur_get_rec(pcur);
264
+ index = btr_pcur_get_btr_cur(pcur)->index;
266
+ if (prebuilt->new_rec_locks >= 2) {
267
+ /* Restore the cursor position and find the record
268
+ in the clustered index. */
270
+ if (!has_latches_on_recs) {
271
+ btr_pcur_restore_position(BTR_SEARCH_LEAF,
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;
282
+ /* If the record has been modified by this
283
+ transaction, do not unlock it. */
284
+ ut_a(dict_index_is_clust(index));
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
290
+ if (index->trx_id_offset) {
291
+ rec_trx_id = trx_read_trx_id(rec
292
+ + index->trx_id_offset);
294
+ mem_heap_t* heap = NULL;
295
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
296
+ ulint* offsets = offsets_;
298
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
299
+ offsets = rec_get_offsets(rec, index, offsets,
300
+ ULINT_UNDEFINED, &heap);
302
- if (dict_index_is_clust(index)) {
303
+ rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
306
+ if (UNIV_LIKELY_NULL(heap)) {
307
+ mem_heap_free(heap);
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 */
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;
321
+ lock_rec_unlock(trx, btr_pcur_get_block(pcur),
322
+ rec, prebuilt->select_lock_type);
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;
329
- if (!has_latches_on_recs) {
330
- btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
332
+ lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
333
+ rec, prebuilt->select_lock_type);
337
- rec = btr_pcur_get_rec(clust_pcur);
339
- lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
340
- rec, prebuilt->select_lock_type);
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 @@
354
*out_rec = clust_rec;
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 */
362
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
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
369
- if ((srv_locks_unsafe_for_binlog
370
- || trx->isolation_level == TRX_ISO_READ_COMMITTED)
371
- && prebuilt->select_lock_type != LOCK_NONE) {
373
- trx_reset_new_rec_lock_info(trx);
375
+ prebuilt->new_rec_locks = 0;
377
/*-------------------------------------------------------------*/
378
/* PHASE 1: Try to pop the row from the prefetch cache */
379
@@ -4056,6 +4051,12 @@
381
const rec_t* old_vers;
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;
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(
396
- trx_reset_new_rec_lock_info(trx);
397
+ prebuilt->new_rec_locks = 0;
399
mutex_exit(&kernel_mutex);
401
@@ -4098,6 +4099,9 @@
405
+ /* Note that a record of
406
+ prebuilt->index was locked. */
407
+ prebuilt->new_rec_locks = 1;
410
mutex_exit(&kernel_mutex);
411
@@ -4246,6 +4250,15 @@
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;
424
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
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;
430
did_semi_consistent_read = FALSE;
432
- if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
433
- || trx->isolation_level == TRX_ISO_READ_COMMITTED)
434
- && prebuilt->select_lock_type != LOCK_NONE) {
436
- trx_reset_new_rec_lock_info(trx);
438
+ prebuilt->new_rec_locks = 0;
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. */
446
- trx_reset_new_rec_lock_info(trx);
447
+ prebuilt->new_rec_locks = 0;
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
455
trx->autoinc_locks = ib_vector_create(
456
mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4);
458
- trx_reset_new_rec_lock_info(trx);