Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
f6f055a1
Commit
f6f055a1
authored
Feb 21, 2022
by
Vlad Lesin
Browse files
Options
Browse Files
Download
Plain Diff
Merge 10.3 into 10.4
parents
fa557986
a6f258e4
Changes
30
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
771 additions
and
398 deletions
+771
-398
include/mysql/plugin.h
include/mysql/plugin.h
+3
-1
mysql-test/main/plugin.result
mysql-test/main/plugin.result
+4
-0
mysql-test/main/plugin.test
mysql-test/main/plugin.test
+1
-0
mysql-test/suite/galera/disabled.def
mysql-test/suite/galera/disabled.def
+1
-0
mysql-test/suite/innodb/r/cursor-restore-locking.result
mysql-test/suite/innodb/r/cursor-restore-locking.result
+35
-0
mysql-test/suite/innodb/r/lock_wait_conflict.result
mysql-test/suite/innodb/r/lock_wait_conflict.result
+27
-0
mysql-test/suite/innodb/t/cursor-restore-locking.test
mysql-test/suite/innodb/t/cursor-restore-locking.test
+79
-0
mysql-test/suite/innodb/t/lock_wait_conflict.test
mysql-test/suite/innodb/t/lock_wait_conflict.test
+60
-0
mysql-test/suite/versioning/r/update.result
mysql-test/suite/versioning/r/update.result
+0
-1
mysql-test/suite/versioning/t/update.test
mysql-test/suite/versioning/t/update.test
+3
-1
sql/sql_plugin.cc
sql/sql_plugin.cc
+6
-4
storage/example/ha_example.cc
storage/example/ha_example.cc
+5
-0
storage/innobase/btr/btr0cur.cc
storage/innobase/btr/btr0cur.cc
+3
-5
storage/innobase/btr/btr0pcur.cc
storage/innobase/btr/btr0pcur.cc
+101
-94
storage/innobase/fts/fts0fts.cc
storage/innobase/fts/fts0fts.cc
+4
-7
storage/innobase/ibuf/ibuf0ibuf.cc
storage/innobase/ibuf/ibuf0ibuf.cc
+2
-1
storage/innobase/include/btr0pcur.h
storage/innobase/include/btr0pcur.h
+39
-24
storage/innobase/include/hash0hash.h
storage/innobase/include/hash0hash.h
+26
-6
storage/innobase/include/lock0lock.h
storage/innobase/include/lock0lock.h
+31
-22
storage/innobase/include/lock0lock.inl
storage/innobase/include/lock0lock.inl
+23
-20
storage/innobase/include/lock0priv.h
storage/innobase/include/lock0priv.h
+19
-4
storage/innobase/include/lock0priv.inl
storage/innobase/include/lock0priv.inl
+45
-20
storage/innobase/include/trx0trx.h
storage/innobase/include/trx0trx.h
+3
-1
storage/innobase/lock/lock0lock.cc
storage/innobase/lock/lock0lock.cc
+178
-109
storage/innobase/lock/lock0prdt.cc
storage/innobase/lock/lock0prdt.cc
+11
-11
storage/innobase/row/row0purge.cc
storage/innobase/row/row0purge.cc
+4
-2
storage/innobase/row/row0sel.cc
storage/innobase/row/row0sel.cc
+34
-35
storage/innobase/row/row0uins.cc
storage/innobase/row/row0uins.cc
+8
-12
storage/innobase/row/row0umod.cc
storage/innobase/row/row0umod.cc
+10
-15
storage/innobase/row/row0upd.cc
storage/innobase/row/row0upd.cc
+6
-3
No files found.
include/mysql/plugin.h
View file @
f6f055a1
...
...
@@ -229,6 +229,7 @@ typedef int (*mysql_show_var_func)(MYSQL_THD, struct st_mysql_show_var*, void *,
#define PLUGIN_VAR_NOCMDARG 0x1000
/* No argument for cmd line */
#define PLUGIN_VAR_RQCMDARG 0x0000
/* Argument required for cmd line */
#define PLUGIN_VAR_OPCMDARG 0x2000
/* Argument optional for cmd line */
#define PLUGIN_VAR_DEPRECATED 0x4000
/* Server variable is deprecated */
#define PLUGIN_VAR_MEMALLOC 0x8000
/* String needs memory allocated */
struct
st_mysql_sys_var
;
...
...
@@ -282,7 +283,8 @@ typedef void (*mysql_var_update_func)(MYSQL_THD thd,
#define PLUGIN_VAR_MASK \
(PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | \
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_NOCMDARG | \
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC)
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | \
PLUGIN_VAR_DEPRECATED | PLUGIN_VAR_MEMALLOC)
#define MYSQL_PLUGIN_VAR_HEADER \
int flags; \
...
...
mysql-test/main/plugin.result
View file @
f6f055a1
...
...
@@ -40,11 +40,15 @@ a
set global example_ulong_var=500;
set global example_enum_var= e1;
set session example_int_var= -1;
set global example_deprecated_var=1;
Warnings:
Warning 1287 '@@example_deprecated_var' is deprecated and will be removed in a future release
show status like 'example%';
Variable_name Value
Example_func_example enum_var is 0, ulong_var is 500, int_var is -1, double_var is 8.500000, really
show variables like 'example%';
Variable_name Value
example_deprecated_var 0
example_double_thdvar 8.500000
example_double_var 8.500000
example_enum_var e1
...
...
mysql-test/main/plugin.test
View file @
f6f055a1
...
...
@@ -27,6 +27,7 @@ SELECT * FROM t1;
set
global
example_ulong_var
=
500
;
set
global
example_enum_var
=
e1
;
set
session
example_int_var
=
-
1
;
set
global
example_deprecated_var
=
1
;
show
status
like
'example%'
;
show
variables
like
'example%'
;
...
...
mysql-test/suite/galera/disabled.def
View file @
f6f055a1
...
...
@@ -14,6 +14,7 @@ GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081
GCF-939 : MDEV-21520 galera.GCF-939
MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002
MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002
MW-328D : MDEV-27550 ER_LOCK_DEADLOCK is gone after MDEV-27025
MW-329 : MDEV-19962 Galera test failure on MW-329
galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event()
galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit
...
...
mysql-test/suite/innodb/r/cursor-restore-locking.result
0 → 100644
View file @
f6f055a1
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot;
connect con_del_1,localhost,root,,;
INSERT INTO t VALUES (20,20);
SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
DELETE FROM t WHERE b = 20;
connect con_ins_1,localhost,root,,;
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
INSERT INTO t VALUES(10, 20);
connect con_del_2,localhost,root,,;
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
DELETE FROM t WHERE b = 20;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
connection con_del_1;
connection default;
disconnect prevent_purge;
InnoDB 0 transactions not purged
SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
connection con_del_2;
connection con_ins_1;
connection default;
INSERT INTO t VALUES(30, 20);
disconnect con_ins_1;
disconnect con_del_1;
disconnect con_del_2;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
mysql-test/suite/innodb/r/lock_wait_conflict.result
0 → 100644
View file @
f6f055a1
#
# MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock
#
CREATE TABLE t (a INT PRIMARY KEY, b INT NOT NULL UNIQUE) ENGINE=InnoDB;
connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot;
connection default;
INSERT INTO t VALUES (20,20);
DELETE FROM t WHERE b = 20;
connect con_ins,localhost,root,,;
SET DEBUG_SYNC = 'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont';
INSERT INTO t VALUES(10, 20);
connect con_del,localhost,root,,;
SET DEBUG_SYNC = 'now WAIT_FOR ins_set_locks';
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL del_locked';
DELETE FROM t WHERE b = 20;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR del_locked';
SET DEBUG_SYNC = 'now SIGNAL ins_cont';
connection con_ins;
disconnect con_ins;
connection con_del;
disconnect con_del;
disconnect prevent_purge;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
mysql-test/suite/innodb/t/cursor-restore-locking.test
0 → 100644
View file @
f6f055a1
--
source
include
/
have_innodb
.
inc
--
source
include
/
count_sessions
.
inc
source
include
/
have_debug
.
inc
;
source
include
/
have_debug_sync
.
inc
;
CREATE
TABLE
t
(
a
int
PRIMARY
KEY
,
b
int
NOT
NULL
UNIQUE
)
engine
=
InnoDB
;
--
connect
(
prevent_purge
,
localhost
,
root
,,)
start
transaction
with
consistent
snapshot
;
--
connect
(
con_del_1
,
localhost
,
root
,,)
INSERT
INTO
t
VALUES
(
20
,
20
);
SET
DEBUG_SYNC
=
'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont'
;
--
send
DELETE
FROM
t
WHERE
b
=
20
--
connect
(
con_ins_1
,
localhost
,
root
,,)
SET
DEBUG_SYNC
=
'now WAIT_FOR first_del_row_search_mvcc_finished'
;
# It's supposed the following INSERT will be suspended just after
# lock_wait_suspend_thread_enter syncpoint, and will be awaken
# after the previous DELETE commits. ib_after_row_insert will be executed
# after the INSERT is woken up. The previous DELETE will wait for
# first_del_cont signal before commit, and this signal will be sent later.
# So it's safe to use two signals in a row here, it's guaranted the first
# signal will be received before the second signal is sent.
SET
DEBUG_SYNC
=
'lock_wait_suspend_thread_enter SIGNAL first_ins_locked'
;
SET
DEBUG_SYNC
=
'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont'
;
--
send
INSERT
INTO
t
VALUES
(
10
,
20
)
--
connect
(
con_del_2
,
localhost
,
root
,,)
SET
DEBUG_SYNC
=
'now WAIT_FOR first_ins_locked'
;
SET
DEBUG_SYNC
=
'lock_wait_suspend_thread_enter SIGNAL second_del_locked'
;
###############################################################################
# This DELETE is locked by the previous DELETE, after that DELETE is
# committed, it will still be locked by the next INSERT on delete-marked
# heap_no 2 record. After that INSERT inserted the record with heap_no 3,
# and after heap_no 2 record is purged, this DELETE will be unlocked and
# must restore persistent cursor position at heap_no 3 record, as it has the
# same secondary key value as former heap_no 2 record. Then it must be blocked
# by the previous INSERT, and after the INSERT is committed, it must
# delete the record, inserted by the previous INSERT, and the last INSERT(see
# below) must be finished without error. But instead this DELETE restores
# persistent cursor position to supremum, as a result, it does not delete the
# record, inserted by the previous INSERT, and the last INSERT is finished with
# duplicate key check error.
###############################################################################
--
send
DELETE
FROM
t
WHERE
b
=
20
--
connection
default
SET
DEBUG_SYNC
=
'now WAIT_FOR second_del_locked'
;
SET
DEBUG_SYNC
=
'now SIGNAL first_del_cont'
;
SET
DEBUG_SYNC
=
'now WAIT_FOR first_ins_row_inserted'
;
--
connection
con_del_1
--
reap
--
connection
default
--
disconnect
prevent_purge
--
source
include
/
wait_all_purged
.
inc
SET
DEBUG_SYNC
=
'now SIGNAL first_ins_cont'
;
--
connection
con_del_2
--
reap
--
connection
con_ins_1
--
reap
--
connection
default
###############################################################################
# Duplicate key error is expected if the bug is not fixed.
###############################################################################
INSERT
INTO
t
VALUES
(
30
,
20
);
--
disconnect
con_ins_1
--
disconnect
con_del_1
--
disconnect
con_del_2
--
connection
default
SET
DEBUG_SYNC
=
'RESET'
;
DROP
TABLE
t
;
--
source
include
/
wait_until_count_sessions
.
inc
mysql-test/suite/innodb/t/lock_wait_conflict.test
0 → 100644
View file @
f6f055a1
--
source
include
/
have_innodb
.
inc
--
source
include
/
count_sessions
.
inc
--
source
include
/
have_debug
.
inc
--
source
include
/
have_debug_sync
.
inc
--
echo
#
--
echo
# MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock
--
echo
#
# The test checks the ability to acquire exclusive record lock if the acquiring
# transaction already holds a shared lock on the record and another transaction
# is waiting for a lock.
CREATE
TABLE
t
(
a
INT
PRIMARY
KEY
,
b
INT
NOT
NULL
UNIQUE
)
ENGINE
=
InnoDB
;
--
connect
(
prevent_purge
,
localhost
,
root
,,)
start
transaction
with
consistent
snapshot
;
--
connection
default
INSERT
INTO
t
VALUES
(
20
,
20
);
DELETE
FROM
t
WHERE
b
=
20
;
--
connect
(
con_ins
,
localhost
,
root
,,)
SET
DEBUG_SYNC
=
'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont'
;
send
INSERT
INTO
t
VALUES
(
10
,
20
);
--
connect
(
con_del
,
localhost
,
root
,,)
SET
DEBUG_SYNC
=
'now WAIT_FOR ins_set_locks'
;
SET
DEBUG_SYNC
=
'lock_wait_suspend_thread_enter SIGNAL del_locked'
;
###############################################################################
# This DELETE creates waiting ORDINARY X-lock for heap_no 2 as the record is
# delete-marked, this lock conflicts with ORDINARY S-lock set by the the last
# INSERT. After the last INSERT creates insert-intention lock on
# heap_no 2, this lock will conflict with waiting ORDINARY X-lock of this
# DELETE, what causes DEADLOCK error for this DELETE.
###############################################################################
send
DELETE
FROM
t
WHERE
b
=
20
;
--
connection
default
SET
DEBUG_SYNC
=
'now WAIT_FOR del_locked'
;
SET
DEBUG_SYNC
=
'now SIGNAL ins_cont'
;
--
connection
con_ins
--
reap
--
disconnect
con_ins
--
connection
con_del
# Without the fix, ER_LOCK_DEADLOCK would be reported here.
--
reap
--
disconnect
con_del
--
disconnect
prevent_purge
--
connection
default
SET
DEBUG_SYNC
=
'RESET'
;
DROP
TABLE
t
;
--
source
include
/
wait_until_count_sessions
.
inc
mysql-test/suite/versioning/r/update.result
View file @
f6f055a1
...
...
@@ -283,7 +283,6 @@ connection default;
update t1 set b = 'foo';
connection con1;
update t1 set a = 'bar';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1;
connection default;
drop table t1;
...
...
mysql-test/suite/versioning/t/update.test
View file @
f6f055a1
...
...
@@ -186,7 +186,9 @@ send update t1 set b = 'foo';
connection
con1
;
let
$wait_condition
=
select
count
(
*
)
from
information_schema
.
innodb_lock_waits
;
source
include
/
wait_condition
.
inc
;
error
ER_LOCK_DEADLOCK
;
# There must no be DEADLOCK here as con1 transaction already holds locks, and
# default's transaction lock is waiting, so the locks of the following "UPDATE"
# must not conflict with waiting lock.
update
t1
set
a
=
'bar'
;
disconnect
con1
;
connection
default
;
...
...
sql/sql_plugin.cc
View file @
f6f055a1
...
...
@@ -292,7 +292,8 @@ class sys_var_pluginvar: public sys_var, public Sql_alloc
struct
st_mysql_sys_var
*
plugin_var
;
sys_var_pluginvar
(
sys_var_chain
*
chain
,
const
char
*
name_arg
,
st_plugin_int
*
p
,
st_mysql_sys_var
*
plugin_var_arg
);
st_plugin_int
*
p
,
st_mysql_sys_var
*
plugin_var_arg
,
const
char
*
substitute
);
sys_var_pluginvar
*
cast_pluginvar
()
{
return
this
;
}
uchar
*
real_value_ptr
(
THD
*
thd
,
enum_var_type
type
)
const
;
TYPELIB
*
plugin_var_typelib
(
void
)
const
;
...
...
@@ -3377,11 +3378,11 @@ static int pluginvar_sysvar_flags(const st_mysql_sys_var *p)
}
sys_var_pluginvar
::
sys_var_pluginvar
(
sys_var_chain
*
chain
,
const
char
*
name_arg
,
st_plugin_int
*
p
,
st_mysql_sys_var
*
pv
)
st_plugin_int
*
p
,
st_mysql_sys_var
*
pv
,
const
char
*
substitute
)
:
sys_var
(
chain
,
name_arg
,
pv
->
comment
,
pluginvar_sysvar_flags
(
pv
),
0
,
pv
->
flags
&
PLUGIN_VAR_NOCMDOPT
?
-
1
:
0
,
NO_ARG
,
pluginvar_show_type
(
pv
),
0
,
NULL
,
VARIABLE_NOT_IN_BINLOG
,
NULL
,
NULL
,
NULL
),
NULL
,
VARIABLE_NOT_IN_BINLOG
,
NULL
,
NULL
,
substitute
),
plugin
(
p
),
plugin_var
(
pv
)
{
plugin_var
->
name
=
name_arg
;
...
...
@@ -4115,7 +4116,8 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
my_casedn_str
(
&
my_charset_latin1
,
varname
);
convert_dash_to_underscore
(
varname
,
len
-
1
);
}
v
=
new
(
mem_root
)
sys_var_pluginvar
(
&
chain
,
varname
,
tmp
,
o
);
const
char
*
s
=
o
->
flags
&
PLUGIN_VAR_DEPRECATED
?
""
:
NULL
;
v
=
new
(
mem_root
)
sys_var_pluginvar
(
&
chain
,
varname
,
tmp
,
o
,
s
);
v
->
test_load
=
(
var
?
&
var
->
loaded
:
&
static_unload
);
DBUG_ASSERT
(
static_unload
==
FALSE
);
...
...
storage/example/ha_example.cc
View file @
f6f055a1
...
...
@@ -1054,12 +1054,17 @@ static MYSQL_THDVAR_DOUBLE(
1000.5
,
0
);
static
MYSQL_THDVAR_INT
(
deprecated_var
,
PLUGIN_VAR_RQCMDARG
|
PLUGIN_VAR_DEPRECATED
,
"-1..1"
,
NULL
,
NULL
,
0
,
-
1
,
1
,
0
);
static
struct
st_mysql_sys_var
*
example_system_variables
[]
=
{
MYSQL_SYSVAR
(
enum_var
),
MYSQL_SYSVAR
(
ulong_var
),
MYSQL_SYSVAR
(
int_var
),
MYSQL_SYSVAR
(
double_var
),
MYSQL_SYSVAR
(
double_thdvar
),
MYSQL_SYSVAR
(
deprecated_var
),
MYSQL_SYSVAR
(
varopt_default
),
NULL
};
...
...
storage/innobase/btr/btr0cur.cc
View file @
f6f055a1
...
...
@@ -7491,11 +7491,9 @@ struct btr_blob_log_check_t {
buf_block_buf_fix_dec
(
m_pcur
->
btr_cur
.
page_cur
.
block
);
}
else
{
ut_ad
(
m_pcur
->
rel_pos
==
BTR_PCUR_ON
);
bool
ret
=
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
|
BTR_MODIFY_EXTERNAL
,
m_pcur
,
m_mtr
);
ut_a
(
ret
);
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
|
BTR_MODIFY_EXTERNAL
,
m_pcur
,
m_mtr
)
==
btr_pcur_t
::
SAME_ALL
);
}
*
m_block
=
btr_pcur_get_block
(
m_pcur
);
...
...
storage/innobase/btr/btr0pcur.cc
View file @
f6f055a1
This diff is collapsed.
Click to expand it.
storage/innobase/fts/fts0fts.cc
View file @
f6f055a1
...
...
@@ -3515,7 +3515,6 @@ fts_add_doc_by_id(
get_doc
,
clust_index
,
doc_pcur
,
offsets
,
&
doc
);
if
(
doc
.
found
)
{
ibool
success
MY_ATTRIBUTE
((
unused
));
btr_pcur_store_position
(
doc_pcur
,
&
mtr
);
mtr_commit
(
&
mtr
);
...
...
@@ -3569,12 +3568,10 @@ fts_add_doc_by_id(
mtr_start
(
&
mtr
);
if
(
i
<
num_idx
-
1
)
{
success
=
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
doc_pcur
,
&
mtr
);
ut_ad
(
success
);
ut_d
(
btr_pcur_t
::
restore_status
status
=
)
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
doc_pcur
,
&
mtr
);
ut_ad
(
status
==
btr_pcur_t
::
SAME_ALL
);
}
}
...
...
storage/innobase/ibuf/ibuf0ibuf.cc
View file @
f6f055a1
...
...
@@ -4139,7 +4139,8 @@ ibuf_restore_pos(
ut_ad
(
mode
==
BTR_MODIFY_LEAF
||
BTR_LATCH_MODE_WITHOUT_INTENTION
(
mode
)
==
BTR_MODIFY_TREE
);
if
(
btr_pcur_restore_position
(
mode
,
pcur
,
mtr
))
{
if
(
btr_pcur_restore_position
(
mode
,
pcur
,
mtr
)
==
btr_pcur_t
::
SAME_ALL
)
{
return
(
TRUE
);
}
...
...
storage/innobase/include/btr0pcur.h
View file @
f6f055a1
...
...
@@ -253,31 +253,9 @@ btr_pcur_store_position(
/*====================*/
btr_pcur_t
*
cursor
,
/*!< in: persistent cursor */
mtr_t
*
mtr
);
/*!< in: mtr */
/**************************************************************//**
Restores the stored position of a persistent cursor bufferfixing the page and
obtaining the specified latches. If the cursor position was saved when the
(1) cursor was positioned on a user record: this function restores the position
to the last record LESS OR EQUAL to the stored record;
(2) cursor was positioned on a page infimum record: restores the position to
the last record LESS than the user record which was the successor of the page
infimum;
(3) cursor was positioned on the page supremum: restores to the first record
GREATER than the user record which was the predecessor of the supremum.
(4) cursor was positioned before the first or after the last in an empty tree:
restores to before first or after the last in the tree.
@return TRUE if the cursor position was stored when it was on a user
record and it can be restored on a user record whose ordering fields
are identical to the ones of the original user record */
ibool
btr_pcur_restore_position_func
(
/*===========================*/
ulint
latch_mode
,
/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t
*
cursor
,
/*!< in: detached persistent cursor */
const
char
*
file
,
/*!< in: file name */
unsigned
line
,
/*!< in: line where called */
mtr_t
*
mtr
);
/*!< in: mtr */
#define btr_pcur_restore_position(l,cur,mtr) \
btr_pcur_restore_position_func(l,cur
,__FILE__,__LINE__,mtr)
(cur)->restore_position(l
,__FILE__,__LINE__,mtr)
/*********************************************************//**
Gets the rel_pos field for a cursor whose position has been stored.
@return BTR_PCUR_ON, ... */
...
...
@@ -482,6 +460,18 @@ enum pcur_pos_t {
selects, updates, and deletes. */
struct
btr_pcur_t
{
/** Return value of restore_position() */
enum
restore_status
{
/** cursor position on user rec and points on the record with
the same field values as in the stored record */
SAME_ALL
,
/** cursor position is on user rec and points on the record with
the same unique field values as in the stored record */
SAME_UNIQ
,
/** cursor position is not on user rec or points on the record
with not the same uniq field values as in the stored record */
NOT_SAME
};
/** a B-tree cursor */
btr_cur_t
btr_cur
;
/** see TODO note below!
...
...
@@ -538,6 +528,31 @@ struct btr_pcur_t{
/** Return the index of this persistent cursor */
dict_index_t
*
index
()
const
{
return
(
btr_cur
.
index
);
}
/** Restores the stored position of a persistent cursor bufferfixing
the page and obtaining the specified latches. If the cursor position
was saved when the
(1) cursor was positioned on a user record: this function restores the
position to the last record LESS OR EQUAL to the stored record;
(2) cursor was positioned on a page infimum record: restores the
position to the last record LESS than the user record which was the
successor of the page infimum;
(3) cursor was positioned on the page supremum: restores to the first
record GREATER than the user record which was the predecessor of the
supremum.
(4) cursor was positioned before the first or after the last in an
empty tree: restores to before first or after the last in the tree.
@param latch_mode BTR_SEARCH_LEAF, ...
@param file file name
@param line line where called
@param mtr mtr
@return btr_pcur_t::SAME_ALL cursor position on user rec and points on
the record with the same field values as in the stored record,
btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the
record with the same unique field values as in the stored record,
btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
the record with not the samebuniq field values as in the stored */
restore_status
restore_position
(
ulint
latch_mode
,
const
char
*
file
,
unsigned
line
,
mtr_t
*
mtr
);
};
#include "btr0pcur.inl"
...
...
storage/innobase/include/hash0hash.h
View file @
f6f055a1
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
Copyright (c) 2018,
2022,
MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -31,7 +31,31 @@ Created 5/20/1997 Heikki Tuuri
#include "sync0rw.h"
struct
hash_table_t
;
struct
hash_cell_t
;
struct
hash_cell_t
{
/** singly-linked, nullptr terminated list of hash buckets */
void
*
node
;
/** Insert an element after another.
@tparam T type of the element
@param after the element after which to insert
@param insert the being-inserted element
@param next the next-element pointer in T */
template
<
typename
T
>
void
insert_after
(
T
&
after
,
T
&
insert
,
T
*
T
::*
next
)
{
#ifdef UNIV_DEBUG
for
(
const
T
*
c
=
static_cast
<
const
T
*>
(
node
);
c
;
c
=
c
->*
next
)
if
(
c
==
&
after
)
goto
found
;
ut_error
;
found:
#endif
insert
.
*
next
=
after
.
*
next
;
after
.
*
next
=
&
insert
;
}
};
typedef
void
*
hash_node_t
;
...
...
@@ -477,10 +501,6 @@ hash_unlock_x_all_but(
hash_table_t
*
table
,
/*!< in: hash table */
rw_lock_t
*
keep_lock
);
/*!< in: lock to keep */
struct
hash_cell_t
{
void
*
node
;
/*!< hash chain node, NULL if none */
};
/* The hash table structure */
struct
hash_table_t
{
enum
hash_table_sync_t
type
;
/*<! type of hash_table. */
...
...
storage/innobase/include/lock0lock.h
View file @
f6f055a1
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2020,
2022,
MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -888,26 +888,29 @@ class lock_sys_t
/*********************************************************************//**
Creates a new record lock and inserts it to the lock queue. Does NOT check
for deadlocks or lock compatibility!
@param[in] c_lock conflicting lock
@param[in] thr thread owning trx
@param[in] type_mode lock mode and wait flag, type is ignored and replaced by
LOCK_REC
@param[in] block buffer block containing the record
@param[in] heap_no heap number of the record
@param[in] index index of record
@param[in,out] trx transaction
@param[in] caller_owns_trx_mutex TRUE if caller owns trx mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */
UNIV_INLINE
lock_t
*
lock_rec_create
(
/*============*/
lock_t
*
lock_rec_create
(
lock_t
*
c_lock
,
#ifdef WITH_WSREP
lock_t
*
c_lock
,
/*!< conflicting lock */
que_thr_t
*
thr
,
/*!< thread owning trx */
que_thr_t
*
thr
,
#endif
ulint
type_mode
,
/*!< in: lock mode and wait
flag, type is ignored and
replaced by LOCK_REC */
const
buf_block_t
*
block
,
/*!< in: buffer block containing
the record */
ulint
heap_no
,
/*!< in: heap number of the record */
dict_index_t
*
index
,
/*!< in: index of record */
trx_t
*
trx
,
/*!< in,out: transaction */
bool
caller_owns_trx_mutex
);
/*!< in: true if caller owns
trx mutex */
ulint
type_mode
,
const
buf_block_t
*
block
,
ulint
heap_no
,
dict_index_t
*
index
,
trx_t
*
trx
,
bool
caller_owns_trx_mutex
,
bool
insert_before_waiting
=
false
);
/*************************************************************//**
Removes a record lock request, waiting or granted, from the queue. */
...
...
@@ -920,6 +923,7 @@ lock_rec_discard(
/** Create a new record lock and inserts it to the lock queue,
without checking for deadlocks or conflicts.
@param[in] c_lock conflicting lock
@param[in] type_mode lock mode and wait flag; type will be replaced
with LOCK_REC
@param[in] space tablespace id
...
...
@@ -929,11 +933,15 @@ without checking for deadlocks or conflicts.
@param[in] index the index tree
@param[in,out] trx transaction
@param[in] holds_trx_mutex whether the caller holds trx->mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */
lock_t
*
lock_rec_create_low
(
lock_t
*
c_lock
,
#ifdef WITH_WSREP
lock_t
*
c_lock
,
/*!< conflicting lock */
que_thr_t
*
thr
,
/*!< thread owning trx */
#endif
ulint
type_mode
,
...
...
@@ -943,9 +951,12 @@ lock_rec_create_low(
ulint
heap_no
,
dict_index_t
*
index
,
trx_t
*
trx
,
bool
holds_trx_mutex
);
bool
holds_trx_mutex
,
bool
insert_before_waiting
=
false
);
/** Enqueue a waiting request for a lock which cannot be granted immediately.
Check for deadlocks.
@param[in] c_lock conflicting lock
@param[in] type_mode the requested lock mode (LOCK_S or LOCK_X)
possibly ORed with LOCK_GAP or
LOCK_REC_NOT_GAP, ORed with
...
...
@@ -964,9 +975,7 @@ Check for deadlocks.
(or it happened to commit) */
dberr_t
lock_rec_enqueue_waiting
(
#ifdef WITH_WSREP
lock_t
*
c_lock
,
/*!< conflicting lock */
#endif
lock_t
*
c_lock
,
ulint
type_mode
,
const
buf_block_t
*
block
,
ulint
heap_no
,
...
...
storage/innobase/include/lock0lock.inl
View file @
f6f055a1
...
...
@@ -101,34 +101,37 @@ lock_hash_get(
/*********************************************************************//**
Creates a new record lock and inserts it to the lock queue. Does NOT check
for deadlocks or lock compatibility!
@param[in] c_lock conflicting lock
@param[in] thr thread owning trx
@param[in] type_mode lock mode and wait flag, type is ignored and replaced by
LOCK_REC
@param[in] block buffer block containing the record
@param[in] heap_no heap number of the record
@param[in] index index of record
@param[in,out] trx transaction
@param[in] caller_owns_trx_mutex TRUE if caller owns trx mutex
@param[in] insert_before_waiting if true, inserts new B-tree record lock
just after the last non-waiting lock of the current transaction which is
located before the first waiting for the current transaction lock, otherwise
the lock is inserted at the end of the queue
@return created lock */
UNIV_INLINE
lock_t*
lock_rec_create(
/*============*/
lock_t *lock_rec_create(lock_t *c_lock,
#ifdef WITH_WSREP
lock_t* c_lock, /*!< conflicting lock */
que_thr_t* thr, /*!< thread owning trx */
que_thr_t *thr,
#endif
ulint type_mode,/*!< in: lock mode and wait
flag, type is ignored and
replaced by LOCK_REC */
const buf_block_t* block, /*!< in: buffer block containing
the record */
ulint heap_no,/*!< in: heap number of the record */
dict_index_t* index, /*!< in: index of record */
trx_t* trx, /*!< in,out: transaction */
bool caller_owns_trx_mutex)
/*!< in: TRUE if caller owns
trx mutex */
ulint type_mode, const buf_block_t *block,
ulint heap_no, dict_index_t *index, trx_t *trx,
bool caller_owns_trx_mutex,
bool insert_before_waiting)
{
btr_assert_not_corrupted(block, index);
return lock_rec_create_low(
return lock_rec_create_low(
c_lock,
#ifdef WITH_WSREP
c_lock,
thr,
thr,
#endif
type_mode,
block->page.id.space(), block->page.id.page_no(),
block->frame, heap_no,
index, trx, caller_owns_trx_mutex
);
block->frame, heap_no,
index, trx,
caller_owns_trx_mutex, insert_before_waiting
);
}
storage/innobase/include/lock0priv.h
View file @
f6f055a1
/*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2018, MariaDB Corporation.
Copyright (c) 2015, 2018,
2022
MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -585,6 +585,9 @@ lock_rec_get_next_const(
/*********************************************************************//**
Gets the first explicit lock request on a record.
@param[in] hash hash chain the lock on
@param[in] page_id page id
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t
*
...
...
@@ -660,15 +663,26 @@ lock_table_has(
/** Set the wait status of a lock.
@param[in,out] lock lock that will be waited for
@param[in,out] trx transaction that will wait for the lock */
inline
void
lock_set_lock_and_trx_wait
(
lock_t
*
lock
,
trx_t
*
trx
)
@param[in,out] trx transaction that will wait for the lock
@param[in] c_lock conflicting lock */
inline
void
lock_set_lock_and_trx_wait
(
lock_t
*
lock
,
trx_t
*
trx
,
const
lock_t
*
c_lock
)
{
ut_ad
(
lock
);
ut_ad
(
lock
->
trx
==
trx
);
ut_ad
(
trx
->
lock
.
wait_lock
==
NULL
);
ut_ad
(
lock_mutex_own
());
ut_ad
(
trx_mutex_own
(
trx
));
if
(
trx
->
lock
.
wait_trx
)
{
ut_ad
(
!
c_lock
||
trx
->
lock
.
wait_trx
==
c_lock
->
trx
);
ut_ad
(
trx
->
lock
.
wait_lock
);
ut_ad
((
*
trx
->
lock
.
wait_lock
).
trx
==
trx
);
}
else
{
ut_ad
(
c_lock
);
trx
->
lock
.
wait_trx
=
c_lock
->
trx
;
ut_ad
(
!
trx
->
lock
.
wait_lock
);
}
trx
->
lock
.
wait_lock
=
lock
;
lock
->
type_mode
|=
LOCK_WAIT
;
}
...
...
@@ -681,6 +695,7 @@ inline void lock_reset_lock_and_trx_wait(lock_t* lock)
ut_ad
(
lock_mutex_own
());
ut_ad
(
lock
->
trx
->
lock
.
wait_lock
==
NULL
||
lock
->
trx
->
lock
.
wait_lock
==
lock
);
lock
->
trx
->
lock
.
wait_trx
=
NULL
;
lock
->
trx
->
lock
.
wait_lock
=
NULL
;
lock
->
type_mode
&=
~
LOCK_WAIT
;
}
...
...
storage/innobase/include/lock0priv.inl
View file @
f6f055a1
...
...
@@ -145,22 +145,19 @@ lock_rec_get_first_on_page_addr(
return
(
NULL
);
}
/*********************************************************************//**
Gets the first record lock on a page, where the page is identified by a
/** Gets the first record lock on a page, where the page is identified by a
pointer to it.
@param[in] lock_hash lock hash table
@param[in] space page's space id
@param[in] page_no page number
@param[in] hash page's hash value in records hash table
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t
*
lock_rec_get_first_on_page
(
/*=======================*/
hash_table_t
*
lock_hash
,
/*!< in: lock hash table */
const
buf_block_t
*
block
)
/*!< in: buffer block */
lock_t
*
lock_rec_get_first_on_page
(
hash_table_t
*
lock_hash
,
ulint
space
,
ulint
page_no
,
ulint
hash
)
{
ut_ad
(
lock_mutex_own
());
ulint
space
=
block
->
page
.
id
.
space
();
ulint
page_no
=
block
->
page
.
id
.
page_no
();
ulint
hash
=
buf_block_get_lock_hash_val
(
block
);
for
(
lock_t
*
lock
=
static_cast
<
lock_t
*>
(
HASH_GET_FIRST
(
lock_hash
,
hash
));
...
...
@@ -177,6 +174,20 @@ lock_rec_get_first_on_page(
return
(
NULL
);
}
/** Gets the first record lock on a page, where the page is identified by a
pointer to it.
@param[in] lock_hash lock hash table
@param[in] block buffer block
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t
*
lock_rec_get_first_on_page
(
hash_table_t
*
lock_hash
,
const
buf_block_t
*
block
)
{
return
lock_rec_get_first_on_page
(
lock_hash
,
block
->
page
.
id
.
space
(),
block
->
page
.
id
.
page_no
(),
buf_block_get_lock_hash_val
(
block
));
}
/*********************************************************************//**
Gets the next explicit lock request on a record.
@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
...
...
@@ -210,21 +221,21 @@ lock_rec_get_next_const(
return
(
lock_rec_get_next
(
heap_no
,
(
lock_t
*
)
lock
));
}
/*********************************************************************//**
Gets the first explicit lock request on a record.
/** Gets the first explicit lock request on a record.
@param[in] hash hash chain the lock on
@param[in] space record's space id
@param[in] page_no record's page number
@param[in] lock_hash_val page's hash value in records hash table
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t
*
lock_rec_get_first
(
/*===============*/
hash_table_t
*
hash
,
/*!< in: hash chain the lock on */
const
buf_block_t
*
block
,
/*!< in: block containing the record */
ulint
heap_no
)
/*!< in: heap number of the record */
lock_t
*
lock_rec_get_first
(
hash_table_t
*
hash
,
ulint
space
,
ulint
page_no
,
uint32_t
lock_hash_val
,
ulint
heap_no
)
{
ut_ad
(
lock_mutex_own
());
for
(
lock_t
*
lock
=
lock_rec_get_first_on_page
(
hash
,
block
);
lock
;
lock
=
lock_rec_get_next_on_page
(
lock
))
{
for
(
lock_t
*
lock
=
lock_rec_get_first_on_page
(
hash
,
space
,
page_no
,
lock_hash_val
);
lock
;
lock
=
lock_rec_get_next_on_page
(
lock
))
{
if
(
lock_rec_get_nth_bit
(
lock
,
heap_no
))
{
return
(
lock
);
}
...
...
@@ -233,6 +244,20 @@ lock_rec_get_first(
return
(
NULL
);
}
/** Gets the first explicit lock request on a record.
@param[in] hash hash chain the lock on
@param[in] block block containing the record
@param[in] heap_no heap number of the record
@return first lock, NULL if none exists */
UNIV_INLINE
lock_t
*
lock_rec_get_first
(
hash_table_t
*
hash
,
const
buf_block_t
*
block
,
ulint
heap_no
)
{
return
lock_rec_get_first
(
hash
,
block
->
page
.
id
.
space
(),
block
->
page
.
id
.
page_no
(),
buf_block_get_lock_hash_val
(
block
),
heap_no
);
}
/*********************************************************************//**
Gets the nth bit of a record lock.
@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/
...
...
storage/innobase/include/trx0trx.h
View file @
f6f055a1
...
...
@@ -425,7 +425,9 @@ struct trx_lock_t {
trx_que_t
que_state
;
/*!< valid when trx->state
== TRX_STATE_ACTIVE: TRX_QUE_RUNNING,
TRX_QUE_LOCK_WAIT, ... */
/** Transaction being waited for; protected by the same mutexes as
wait_lock */
trx_t
*
wait_trx
;
lock_t
*
wait_lock
;
/*!< if trx execution state is
TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is
...
...
storage/innobase/lock/lock0lock.cc
View file @
f6f055a1
This diff is collapsed.
Click to expand it.
storage/innobase/lock/lock0prdt.cc
View file @
f6f055a1
/*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
Copyright (c) 2018,
2022
MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -487,9 +487,13 @@ lock_prdt_add_to_queue(
}
}
lock
=
lock_rec_create
(
/* Note: We will not pass any conflicting lock to lock_rec_create(),
because we should be moving an existing waiting lock request. */
ut_ad
(
!
(
type_mode
&
LOCK_WAIT
)
||
trx
->
lock
.
wait_trx
);
lock
=
lock_rec_create
(
NULL
,
#ifdef WITH_WSREP
NULL
,
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
#endif
type_mode
,
block
,
PRDT_HEAPNO
,
index
,
trx
,
caller_owns_trx_mutex
);
...
...
@@ -579,9 +583,7 @@ lock_prdt_insert_check_and_lock(
trx_mutex_enter
(
trx
);
err
=
lock_rec_enqueue_waiting
(
#ifdef WITH_WSREP
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
#endif
LOCK_X
|
LOCK_PREDICATE
|
LOCK_INSERT_INTENTION
,
block
,
PRDT_HEAPNO
,
index
,
thr
,
prdt
);
...
...
@@ -829,9 +831,9 @@ lock_prdt_lock(
lock_t
*
lock
=
lock_rec_get_first_on_page
(
hash
,
block
);
if
(
lock
==
NULL
)
{
lock
=
lock_rec_create
(
lock
=
lock_rec_create
(
NULL
,
#ifdef WITH_WSREP
NULL
,
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
#endif
ulint
(
mode
)
|
type_mode
,
block
,
PRDT_HEAPNO
,
index
,
trx
,
FALSE
);
...
...
@@ -861,10 +863,8 @@ lock_prdt_lock(
if
(
wait_for
!=
NULL
)
{
err
=
lock_rec_enqueue_waiting
(
#ifdef WITH_WSREP
NULL
,
/* FIXME: replicate
SPATIAL INDEX locks */
#endif
ulint
(
mode
)
|
type_mode
,
block
,
PRDT_HEAPNO
,
index
,
thr
,
prdt
);
...
...
@@ -948,9 +948,9 @@ lock_place_prdt_page_lock(
}
if
(
lock
==
NULL
)
{
lock
=
lock_rec_create_low
(
lock
=
lock_rec_create_low
(
NULL
,
#ifdef WITH_WSREP
NULL
,
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
NULL
,
/* FIXME: replicate SPATIAL INDEX locks */
#endif
mode
,
space
,
page_no
,
NULL
,
PRDT_HEAPNO
,
index
,
trx
,
FALSE
);
...
...
storage/innobase/row/row0purge.cc
View file @
f6f055a1
...
...
@@ -73,7 +73,9 @@ row_purge_reposition_pcur(
if
(
node
->
found_clust
)
{
ut_ad
(
node
->
validate_pcur
());
node
->
found_clust
=
btr_pcur_restore_position
(
mode
,
&
node
->
pcur
,
mtr
);
node
->
found_clust
=
btr_pcur_restore_position
(
mode
,
&
node
->
pcur
,
mtr
)
==
btr_pcur_t
::
SAME_ALL
;
}
else
{
node
->
found_clust
=
row_search_on_row_ref
(
...
...
@@ -256,7 +258,7 @@ static bool row_purge_restore_vsec_cur(
return
btr_pcur_restore_position
(
is_tree
?
BTR_PURGE_TREE
:
BTR_PURGE_LEAF
,
sec_pcur
,
sec_mtr
);
sec_pcur
,
sec_mtr
)
==
btr_pcur_t
::
SAME_ALL
;
}
/** Determines if it is possible to remove a secondary index entry.
...
...
storage/innobase/row/row0sel.cc
View file @
f6f055a1
...
...
@@ -1434,8 +1434,9 @@ row_sel_restore_pcur_pos(
relative_position
=
btr_pcur_get_rel_pos
(
&
(
plan
->
pcur
));
equal_position
=
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
&
(
plan
->
pcur
),
mtr
);
equal_position
=
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
&
plan
->
pcur
,
mtr
)
==
btr_pcur_t
::
SAME_ALL
;
/* If the cursor is traveling upwards, and relative_position is
...
...
@@ -3579,36 +3580,29 @@ Row_sel_get_clust_rec_for_mysql::operator()(
return
(
err
);
}
/********************************************************************//**
Restores cursor position after it has been stored. We have to take into
/** Restores cursor position after it has been stored. We have to take into
account that the record cursor was positioned on may have been deleted.
Then we may have to move the cursor one step up or down.
@param[out] same_user_rec true if we were able to restore the cursor on a user
record with the same ordering prefix in in the B-tree index
@param[in] latch_mode latch mode wished in restoration
@param[in] pcur cursor whose position has been stored
@param[in] moves_up true if the cursor moves up in the index
@param[in] mtr mtr; CAUTION: may commit mtr temporarily!
@param[in] select_lock_type select lock type: LOCK_NONE, LOCK_S, or LOCK_X
@return true if we may need to process the record the cursor is now
positioned on (i.e. we should not go to the next record yet) */
static
bool
sel_restore_position_for_mysql
(
/*===========================*/
ibool
*
same_user_rec
,
/*!< out: TRUE if we were able to restore
the cursor on a user record with the
same ordering prefix in in the
B-tree index */
ulint
latch_mode
,
/*!< in: latch mode wished in
restoration */
btr_pcur_t
*
pcur
,
/*!< in: cursor whose position
has been stored */
ibool
moves_up
,
/*!< in: TRUE if the cursor moves up
in the index */
mtr_t
*
mtr
)
/*!< in: mtr; CAUTION: may commit
mtr temporarily! */
static
bool
sel_restore_position_for_mysql
(
bool
*
same_user_rec
,
ulint
latch_mode
,
btr_pcur_t
*
pcur
,
bool
moves_up
,
mtr_t
*
mtr
,
ulint
select_lock_type
)
{
ibool
success
;
success
=
btr_pcur_restore_position
(
latch_mode
,
pcur
,
mtr
);
btr_pcur_t
::
restore_status
status
=
btr_pcur_restore_position
(
latch_mode
,
pcur
,
mtr
);
*
same_user_rec
=
s
uccess
;
*
same_user_rec
=
s
tatus
==
btr_pcur_t
::
SAME_ALL
;
ut_ad
(
!
success
||
pcur
->
rel_pos
==
BTR_PCUR_ON
);
ut_ad
(
!
*
same_user_rec
||
pcur
->
rel_pos
==
BTR_PCUR_ON
);
#ifdef UNIV_DEBUG
if
(
pcur
->
pos_state
==
BTR_PCUR_IS_POSITIONED_OPTIMISTIC
)
{
ut_ad
(
pcur
->
rel_pos
==
BTR_PCUR_BEFORE
...
...
@@ -3624,7 +3618,10 @@ sel_restore_position_for_mysql(
switch
(
pcur
->
rel_pos
)
{
case
BTR_PCUR_ON
:
if
(
!
success
&&
moves_up
)
{
if
(
!*
same_user_rec
&&
moves_up
)
{
if
(
status
==
btr_pcur_t
::
SAME_UNIQ
&&
select_lock_type
!=
LOCK_NONE
)
return
true
;
next:
if
(
btr_pcur_move_to_next
(
pcur
,
mtr
)
&&
rec_is_metadata
(
btr_pcur_get_rec
(
pcur
),
...
...
@@ -3634,7 +3631,7 @@ sel_restore_position_for_mysql(
return
true
;
}
return
(
!
success
);
return
(
!
*
same_user_rec
);
case
BTR_PCUR_AFTER_LAST_IN_TREE
:
case
BTR_PCUR_BEFORE_FIRST_IN_TREE
:
return
true
;
...
...
@@ -4303,7 +4300,7 @@ row_search_mvcc(
dberr_t
err
=
DB_SUCCESS
;
ibool
unique_search
=
FALSE
;
ibool
mtr_has_extra_clust_latch
=
FALSE
;
ibool
moves_up
=
FALSE
;
bool
moves_up
=
false
;
ibool
set_also_gap_locks
=
TRUE
;
/* if the query is a plain locking SELECT, and the isolation level
is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */
...
...
@@ -4312,7 +4309,7 @@ row_search_mvcc(
read (fetch the newest committed version), then this is set to
TRUE */
ulint
next_offs
;
i
bool
same_user_rec
;
bool
same_user_rec
;
mtr_t
mtr
;
mem_heap_t
*
heap
=
NULL
;
rec_offs
offsets_
[
REC_OFFS_NORMAL_SIZE
];
...
...
@@ -4623,10 +4620,10 @@ row_search_mvcc(
if
(
UNIV_UNLIKELY
(
direction
==
0
))
{
if
(
mode
==
PAGE_CUR_GE
||
mode
==
PAGE_CUR_G
||
mode
>=
PAGE_CUR_CONTAIN
)
{
moves_up
=
TRUE
;
moves_up
=
true
;
}
}
else
if
(
direction
==
ROW_SEL_NEXT
)
{
moves_up
=
TRUE
;
moves_up
=
true
;
}
thr
=
que_fork_get_first_thr
(
prebuilt
->
sel_graph
);
...
...
@@ -4676,7 +4673,7 @@ row_search_mvcc(
bool
need_to_process
=
sel_restore_position_for_mysql
(
&
same_user_rec
,
BTR_SEARCH_LEAF
,
pcur
,
moves_up
,
&
mtr
);
pcur
,
moves_up
,
&
mtr
,
prebuilt
->
select_lock_type
);
if
(
UNIV_UNLIKELY
(
need_to_process
))
{
if
(
UNIV_UNLIKELY
(
prebuilt
->
row_read_type
...
...
@@ -4898,7 +4895,7 @@ row_search_mvcc(
if
(
UNIV_UNLIKELY
(
next_offs
>=
srv_page_size
-
PAGE_DIR
))
{
wrong_offs:
if
(
srv_force_recovery
==
0
||
moves_up
==
FALSE
)
{
if
(
srv_force_recovery
==
0
||
moves_up
==
false
)
{
ib
::
error
()
<<
"Rec address "
<<
static_cast
<
const
void
*>
(
rec
)
<<
", buf block fix count "
...
...
@@ -5701,7 +5698,9 @@ row_search_mvcc(
if
(
sel_restore_position_for_mysql
(
&
same_user_rec
,
BTR_SEARCH_LEAF
,
pcur
,
moves_up
,
&
mtr
))
{
pcur
,
moves_up
,
&
mtr
,
prebuilt
->
select_lock_type
)
)
{
goto
rec_loop
;
}
}
...
...
@@ -5792,7 +5791,7 @@ row_search_mvcc(
if
(
!
dict_index_is_spatial
(
index
))
{
sel_restore_position_for_mysql
(
&
same_user_rec
,
BTR_SEARCH_LEAF
,
pcur
,
moves_up
,
&
mtr
);
moves_up
,
&
mtr
,
prebuilt
->
select_lock_type
);
}
if
((
srv_locks_unsafe_for_binlog
...
...
storage/innobase/row/row0uins.cc
View file @
f6f055a1
...
...
@@ -65,7 +65,6 @@ row_undo_ins_remove_clust_rec(
/*==========================*/
undo_node_t
*
node
)
/*!< in: undo node */
{
ibool
success
;
dberr_t
err
;
ulint
n_tries
=
0
;
mtr_t
mtr
;
...
...
@@ -102,12 +101,12 @@ row_undo_ins_remove_clust_rec(
purged. However, we can log the removal out of sync with the
B-tree modification. */
success
=
btr_pcur_restore_position
(
ut_a
(
btr_pcur_restore_position
(
online
?
BTR_MODIFY_LEAF
|
BTR_ALREADY_S_LATCHED
:
(
node
->
rec_type
==
TRX_UNDO_INSERT_METADATA
)
?
BTR_MODIFY_TREE
:
BTR_MODIFY_LEAF
,
&
node
->
pcur
,
&
mtr
)
;
ut_a
(
success
);
?
BTR_MODIFY_TREE
:
BTR_MODIFY_LEAF
,
&
node
->
pcur
,
&
mtr
)
==
btr_pcur_t
::
SAME_ALL
);
rec_t
*
rec
=
btr_pcur_get_rec
(
&
node
->
pcur
);
...
...
@@ -138,9 +137,9 @@ row_undo_ins_remove_clust_rec(
mtr
.
commit
();
mtr
.
start
();
success
=
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
&
node
->
pcur
,
&
mtr
)
;
ut_a
(
success
);
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
&
node
->
pcur
,
&
mtr
)
==
btr_pcur_t
::
SAME_ALL
);
break
;
case
DICT_COLUMNS_ID
:
/* This is rolling back an INSERT into SYS_COLUMNS.
...
...
@@ -181,11 +180,8 @@ row_undo_ins_remove_clust_rec(
}
else
{
index
->
set_modified
(
mtr
);
}
success
=
btr_pcur_restore_position
(
BTR_MODIFY_TREE
|
BTR_LATCH_FOR_DELETE
,
&
node
->
pcur
,
&
mtr
);
ut_a
(
success
);
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_TREE
|
BTR_LATCH_FOR_DELETE
,
&
node
->
pcur
,
&
mtr
)
==
btr_pcur_t
::
SAME_ALL
);
btr_cur_pessimistic_delete
(
&
err
,
FALSE
,
&
node
->
pcur
.
btr_cur
,
0
,
true
,
&
mtr
);
...
...
storage/innobase/row/row0umod.cc
View file @
f6f055a1
...
...
@@ -95,19 +95,14 @@ row_undo_mod_clust_low(
btr_pcur_t
*
pcur
;
btr_cur_t
*
btr_cur
;
dberr_t
err
;
#ifdef UNIV_DEBUG
ibool
success
;
#endif
/* UNIV_DEBUG */
pcur
=
&
node
->
pcur
;
btr_cur
=
btr_pcur_get_btr_cur
(
pcur
);
#ifdef UNIV_DEBUG
success
=
#endif
/* UNIV_DEBUG */
ut_d
(
btr_pcur_t
::
restore_status
pcur_restore_result
=
)
btr_pcur_restore_position
(
mode
,
pcur
,
mtr
);
ut_ad
(
success
);
ut_ad
(
pcur_restore_result
==
btr_pcur_t
::
SAME_ALL
);
ut_ad
(
rec_get_trx_id
(
btr_cur_get_rec
(
btr_cur
),
btr_cur_get_index
(
btr_cur
))
==
thr_get_trx
(
thr
)
->
id
...
...
@@ -388,7 +383,8 @@ row_undo_mod_clust(
ut_ad
(
node
->
new_trx_id
);
mtr
.
start
();
if
(
!
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
))
{
if
(
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
)
!=
btr_pcur_t
::
SAME_ALL
)
{
goto
mtr_commit_exit
;
}
...
...
@@ -410,9 +406,9 @@ row_undo_mod_clust(
btr_pcur_commit_specify_mtr
(
pcur
,
&
mtr
);
mtr
.
start
();
if
(
!
btr_pcur_restore_position
(
if
(
btr_pcur_restore_position
(
BTR_MODIFY_TREE
|
BTR_LATCH_FOR_DELETE
,
pcur
,
&
mtr
))
{
pcur
,
&
mtr
)
!=
btr_pcur_t
::
SAME_ALL
)
{
goto
mtr_commit_exit
;
}
...
...
@@ -444,7 +440,8 @@ row_undo_mod_clust(
longer accessible by any active read view. */
mtr
.
start
();
if
(
!
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
))
{
if
(
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
)
!=
btr_pcur_t
::
SAME_ALL
)
{
goto
mtr_commit_exit
;
}
rec_t
*
rec
=
btr_pcur_get_rec
(
pcur
);
...
...
@@ -541,7 +538,6 @@ row_undo_mod_del_mark_or_remove_sec_low(
{
btr_pcur_t
pcur
;
btr_cur_t
*
btr_cur
;
ibool
success
;
dberr_t
err
=
DB_SUCCESS
;
mtr_t
mtr
;
mtr_t
mtr_vers
;
...
...
@@ -613,9 +609,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
mtr_vers
.
start
();
success
=
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
&
(
node
->
pcur
),
&
mtr_vers
);
ut_a
(
success
);
ut_a
(
btr_pcur_restore_position
(
BTR_SEARCH_LEAF
,
&
node
->
pcur
,
&
mtr_vers
)
==
btr_pcur_t
::
SAME_ALL
);
/* For temporary table, we can skip to check older version of
clustered index entry, because there is no MVCC or purge. */
...
...
storage/innobase/row/row0upd.cc
View file @
f6f055a1
...
...
@@ -2919,7 +2919,8 @@ row_upd_clust_rec(
the same transaction do not modify the record in the meantime.
Therefore we can assert that the restoration of the cursor succeeds. */
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_TREE
,
pcur
,
mtr
));
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_TREE
,
pcur
,
mtr
)
==
btr_pcur_t
::
SAME_ALL
);
ut_ad
(
!
rec_get_deleted_flag
(
btr_pcur_get_rec
(
pcur
),
dict_table_is_comp
(
index
->
table
)));
...
...
@@ -3122,7 +3123,8 @@ row_upd_clust_step(
mode
=
BTR_MODIFY_LEAF
;
}
if
(
!
btr_pcur_restore_position
(
mode
,
pcur
,
&
mtr
))
{
if
(
btr_pcur_restore_position
(
mode
,
pcur
,
&
mtr
)
!=
btr_pcur_t
::
SAME_ALL
)
{
err
=
DB_RECORD_NOT_FOUND
;
goto
exit_func
;
}
...
...
@@ -3144,7 +3146,8 @@ row_upd_clust_step(
mtr
.
start
();
index
->
set_modified
(
mtr
);
if
(
!
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
))
{
if
(
btr_pcur_restore_position
(
BTR_MODIFY_LEAF
,
pcur
,
&
mtr
)
!=
btr_pcur_t
::
SAME_ALL
)
{
err
=
DB_ERROR
;
goto
exit_func
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment