File: rr_u_10-19.test

package info (click to toggle)
mariadb 1%3A11.8.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 772,520 kB
  • sloc: ansic: 2,414,714; cpp: 1,791,394; asm: 381,336; perl: 62,905; sh: 49,647; pascal: 40,897; java: 39,363; python: 20,791; yacc: 20,432; sql: 17,907; xml: 12,344; ruby: 8,544; cs: 6,542; makefile: 6,145; ada: 1,879; lex: 1,193; javascript: 996; objc: 80; tcl: 73; awk: 46; php: 22
file content (406 lines) | stat: -rw-r--r-- 15,783 bytes parent folder | download | duplicates (19)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
######################################################################################
#
# Using UPDATE statements in order to:
#  - move a record outside the curent index extremities (min and max values).
#  - move a record forward and backward in the index (add and subtract some number).
#  - move a record into, out of and inside a locked index interval.
#
# This test is using FOR UPDATE to lock index ranges and to make sure we do not
# base new values on old record versions (in the face of concurrent updates).
#
# Need to handle any tx errors, ROLLBACK if needed to maintain table consistency.
#
# This test runs several transactions, each transaction executing one or more
# UPDATE statements and potentially other helping SELECT queries.
#
# If we pick a row (pk) by random that does not exist, it does not matter (will try
# again next time), but we should probably keep this to a minimum.
#
# We need a way to maintain table consistency when updating a field with an arbitrary
# number. Using this algorithm:
#  * We need to know: How much does the table sum change with this update?
#  * Change is: <new value> - <old value>.
#  * We must then add back the negative of that to a different field in the table.
#  
#    Example: Columns a and b with values a = a1, b = b1
#      We want to update a to a2. We need to figure out what b2 should be.
#      - Save a1 (e.g. as user variable)
#      - Update a to a2 and b to b2 = b - (a2 - a1)
#      - In other words: a changed with a2 - a1.
#                        b changed with b2 - b1 = b1 - (a2 - a1) - b1 = -(a2 - a1)
#            => Zero-sum change.
#
# NOTE: Consider splitting this up into multiple test files if we get too many
#       skips due to locking errors (see check_for_error_rollback_skip.inc) .
######################################################################################

SET autocommit = 0;

###################
# Transaction 1
###################

--echo
--echo *** Move record out of locked portion of index:
--echo
START TRANSACTION;

--echo *** Disabling result log (result will vary)
--disable_result_log
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `int1_key` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_key`, `pk` LIMIT 10 FOR UPDATE;

# Even if SELECT FOR UPDATE failed, we can continue - we just don't necessarily move the row out of locked portion of index.

# We (may) have locked some records (if any were found).
# Set an int1_key to a value outside of this range.
# First pick a pk. We may use this later in the transaction.
SELECT @pk:=`pk` FROM t1 WHERE `int1_key` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_key`, `pk` LIMIT 1;

--echo *** Enabling result log
--enable_result_log

# We should mark row as consistent if the row-sum is 0.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int1_key` = `int1_key` + 50,
              `int2_key` = `int2_key` - 50,
              `id` = 10,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;

###################
# Transaction 2
###################

--echo
--echo *** Move record out of locked portion of UNIQUE index:
--echo
START TRANSACTION;

--echo *** Disabling result log (result will vary)
--disable_result_log
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `int1_unique` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_unique` LIMIT 10 FOR UPDATE;

# Even if SELECT FOR UPDATE failed, we can continue - we just don't necessarily move the row out of locked portion of index.

# We (may) have locked some records (if any were found)
# Set an int1_unique to a value outside of this range.
# First pick a pk to use several times later in the transaction.
SELECT @pk:=`pk` FROM t1 WHERE `int1_unique` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_unique` LIMIT 1;

--echo *** Enabling result log
--enable_result_log

# We should mark row as consistent if the row-sum is 0.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD, ER_DUP_ENTRY
UPDATE t1 SET `int1_unique` = `int1_unique` + 50 + CONNECTION_ID(),
              `int2_unique` = `int2_unique` - 50 - CONNECTION_ID(),
              `id` = 11,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;

###################
# Transaction 3
###################
# Not doing this for unique index (too tricky to avoid DUP_ENTRY...)

--echo
--echo *** Move record into locked portion of index:
--echo
START TRANSACTION;

--echo *** Disabling result log (result will vary)
--disable_result_log
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `int1_key` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_key`, `pk` LIMIT 10 FOR UPDATE;

# If the above statement resulted in deadlock we can still continue - the test will just try to do UPDATEs without explicitly locking first.

# We (may) have locked some records (if any were found)
# Set an int1_key to a value outside of this range.
# Pick a pk to use later in the transaction. Select one that is outside of the locked range.
SELECT @pk:=`pk` FROM t1 WHERE `int1_key` > 1030 ORDER BY `int1_key`, `pk` LIMIT 1;

--echo *** Enabling result log
--enable_result_log

# We should mark row as consistent if the row-sum is 0.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int1_key` = `int1_key` + 50,
              `int2_key` = `int2_key` - 50,
              `id` = 12,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;

###################
# Transaction 4
###################
# Not doing this for unique index (too tricky to avoid DUP_ENTRY...)

--echo
--echo *** Move record inside locked portion of index (move it but stay inside the locked range):
--echo
START TRANSACTION;

--echo *** Disabling result log (result will vary)
--disable_result_log
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `int1_key` BETWEEN 981 + (CONNECTION_ID() MOD 15) AND 1030 ORDER BY `int1_key`, `pk` LIMIT 10 FOR UPDATE;

# If the above statement resulted in deadlock we can still continue - the test will just try to do UPDATEs without explicitly locking first.

# We (may) have locked some records (if any were found)
# Set an int1_key to a value outside of this range.
# Pick a pk to use later in the transaction. Select one that is outside of the locked range.
SELECT @pk:=`pk` FROM t1 WHERE `int1_key` BETWEEN  981 + 10 + (CONNECTION_ID() MOD 15) AND 1019 ORDER BY `int1_key`, `pk` LIMIT 1;

--echo *** Enabling result log
--enable_result_log

# We should mark row as consistent if the row-sum is 0.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int1_key` = `int1_key` - 10,
              `int2_key` = `int2_key` + 10,
              `id` = 13,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;

###################
# Transaction 5
###################

--echo
--echo *** Move record outside existing index boundary (max):
--echo
START TRANSACTION;

--echo *** Disabling result log (results will vary)
--disable_result_log

# Get the max value of `int2_key`.
# Pick a random pk value.
# The pk identifies a row that we want to update to move its int2_key value above the current MAX.
SELECT @max:=MAX(`int2_key`), @pk:=FLOOR(1 + RAND() * (MAX(`pk`) - 1)) FROM t1;

# Get the current value of `int2_key` of the row we are going to update.
# We need this to be able to calculate values for maintaining table consistency.
# Also, we should mark row as consistent if the row-sum is 0, so calculate the sum of the data ints.
# Hence, we need to lock the row to avoid concurrent modifications.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `pk` = @pk FOR UPDATE;

# Do not continue if the above FOR UPDATE locking fails - we may end up making the table/row inconstistent.
--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

SELECT @old:=`int2_key`, (@sum:=`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique`) FROM t1 WHERE `pk` = @pk;

--echo *** Enabling result log
--enable_result_log

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int2_key` = @max + 1,
              `int2` = `int2` - (@max + 1 - @old),
              `id` = 14,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(@sum = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;

## Do the same with a UNIQUE index

###################
# Transaction 6
###################

--echo
--echo *** Move record outside existing UNIQUE index boundary (max):
--echo
START TRANSACTION;

--echo *** Disabling result log (results will vary)
--disable_result_log

# Get the max value of `int2_unique`.
# Pick a random pk value.
# The pk identifies a row that we want to update to move its int2_key value above the current MAX.
SELECT @max:=MAX(`int2_unique`), @pk:=FLOOR(1 + RAND() * (MAX(`pk`) - 1)) FROM t1;

# Get the current value of `int2_key` of the row we are going to update.
# We need this to be able to calculate values for maintaining table consistency.
# Also, we should mark row as consistent if the row-sum is 0, so calculate the sum of the data ints.
# We need to lock the row to avoid concurrent "silent" modifications.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `pk` = @pk FOR UPDATE;

# Do not continue if the above FOR UPDATE locking fails - we may end up making the table/row inconstistent.
--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

SELECT @old:=`int2_unique`, (@sum:=`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique`) FROM t1 WHERE `pk` = @pk;

--echo *** Enabling result log
--enable_result_log

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD, ER_DUP_ENTRY
UPDATE t1 SET `int2_unique` = @max + 1,
              `int2` = `int2` - (@max + 1 - @old),
              `id` = 15,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(@sum = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

# Verify sum after update:
if(`SELECT IF(`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` <> 0 AND `is_consistent` = 1, 1, 0) WHERE `pk` = @pk`)
{
    --echo FAIL - updated row, set is_consistent = 1 but sum is not 0!
    SELECT `pk`, `int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique` WHERE `pk` = @pk;
}

COMMIT;


###################
# Transaction 7
###################

--echo
--echo *** Move record outside existing index boundary (min):
--echo
START TRANSACTION;

--echo *** Disabling result log (results will vary)
--disable_result_log

# Get the min value of `int1_key`.
# Pick a random pk value.
# The pk identifies a row that we want to update to move its int1_key value below the current MIN.
SELECT @min:=MIN(`int1_key`), @pk:=FLOOR(1 + RAND() * (MAX(`pk`) - 1)) FROM t1;

# Get the current value of `int1_key` of the row we are going to update.
# We need this to be able to calculate values for maintaining table consistency.
# Also, we should mark row as consistent if the row-sum is 0, so calculate the sum of the data ints.
# Hence, we need to lock the row to avoid concurrent modifications.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `pk` = @pk FOR UPDATE;

# Do not continue if the above FOR UPDATE locking fails - we may end up making the table/row inconstistent.
--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

SELECT @old:=`int1_key`, (@sum:=`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique`) FROM t1 WHERE `pk` = @pk;

--echo *** Enabling result log
--enable_result_log

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int1_key` = @min - 1,
              `int1` = `int1` - (@min - 1 - @old),
              `id` = 16,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(@sum = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;
## Do the same with a UNIQUE index

###################
# Transaction 8
###################

--echo
--echo *** Move record outside existing UNIQUE index boundary (min):
--echo
START TRANSACTION;

--echo *** Disabling result log (results will vary)
--disable_result_log

# Get the max value of `int1_unique`.
# Pick a random pk value.
# The pk identifies a row that we want to update to move its int2_key value above the current MAX.
SELECT @min:=MIN(`int1_unique`), @pk:=FLOOR(1 + RAND() * (MAX(`pk`) - 1)) FROM t1;

# Get the current value of `int2_key` of the row we are going to update.
# We need this to be able to calculate values for maintaining table consistency.
# Also, we should mark row as consistent if the row-sum is 0, so calculate the sum of the data ints.
# Hence, we need to lock the row to avoid concurrent modifications.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT * FROM t1 WHERE `pk` = @pk FOR UPDATE;

# Do not continue if the above FOR UPDATE locking fails - we may end up making the table/row inconstistent.
--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

SELECT @old:=`int1_unique`, (@sum:=`int1` + `int2` + `int1_key` + `int2_key` + `int1_unique` + `int2_unique`) FROM t1 WHERE `pk` = @pk;

--echo *** Enabling result log
--enable_result_log

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD, ER_DUP_ENTRY
UPDATE t1 SET `int1_unique` = @min - 1,
              `int1` = `int1` - (@min - 1 - @old),
              `id` = 17,
              `connection_id` = CONNECTION_ID(),
              `is_consistent` = IF(@sum = 0, 1, 0),
              `thread_id` = 0
     WHERE `pk` = @pk;

COMMIT;


###################
# Transaction 9
###################

--echo
--echo *** Move record forward in index (add some number):
--echo
START TRANSACTION;

# Updating a "random" row.
# Subtract the same number from another field to maintain consistency.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int2_key` = `int2_key` + 16,
              `int2` = `int2` - 16,
              `id` = 18,
              `connection_id` = CONNECTION_ID(),
              `thread_id` = 0
     WHERE `pk` = CONNECTION_ID() MOD 1000;

## Skip the same with a UNIQUE index (we need to update to > MAX or find some missing value in the middle). See MAX update in previous transactions.

--echo
--echo *** Move record backward in index (subtract some number):
--echo

# Updating a "random" row.
# Add the same number to another field to maintain consistency.
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
UPDATE t1 SET `int1_key` = `int1_key` - 16,
              `int1` = `int1` + 16,
              `id` = 18,
              `connection_id` = CONNECTION_ID(),
              `thread_id` = 0
     WHERE `pk` = CONNECTION_ID() + 16 MOD 1000;

COMMIT;