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
acd695d8
Commit
acd695d8
authored
Dec 25, 2010
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge MWL#163 into mariadb-5.2-rpl
parents
db3c8fba
e7b024b6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
319 additions
and
1 deletion
+319
-1
mysql-test/r/innodb_release_row_locks_early.result
mysql-test/r/innodb_release_row_locks_early.result
+102
-0
mysql-test/t/innodb_release_row_locks_early-master.opt
mysql-test/t/innodb_release_row_locks_early-master.opt
+1
-0
mysql-test/t/innodb_release_row_locks_early.test
mysql-test/t/innodb_release_row_locks_early.test
+131
-0
sql/log.cc
sql/log.cc
+3
-0
storage/xtradb/handler/ha_innodb.cc
storage/xtradb/handler/ha_innodb.cc
+68
-0
storage/xtradb/include/srv0srv.h
storage/xtradb/include/srv0srv.h
+3
-0
storage/xtradb/include/trx0sys.ic
storage/xtradb/include/trx0sys.ic
+8
-1
storage/xtradb/srv/srv0srv.c
storage/xtradb/srv/srv0srv.c
+3
-0
No files found.
mysql-test/r/innodb_release_row_locks_early.result
0 → 100644
View file @
acd695d8
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (k INT NOT NULL, a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, PRIMARY KEY(k)) ENGINE=InnoDB;
INSERT INTO t1 (k, a, b, c) VALUES (1, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (2, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (3, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (4, 0, 0, 0);
RESET MASTER;
SET DEBUG_SYNC= 'RESET';
# Connection c1
BEGIN;
UPDATE t1 SET a=10 WHERE k=1;
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing";
COMMIT;
# Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
BEGIN;
SELECT * FROM t1 WHERE k=1 FOR UPDATE;
k a b c
1 10 0 0
UPDATE t1 SET a=20 WHERE k=1;
SET DEBUG_SYNC="now SIGNAL c2_committing";
COMMIT;
# Connection c1
BEGIN;
UPDATE t1 SET a=10 WHERE k=2;
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2";
COMMIT;
# Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
BEGIN;
SELECT * FROM t1 WHERE k=2 FOR UPDATE;
k a b c
2 10 0 0
UPDATE t1 SET a=20 WHERE k=2;
SET DEBUG_SYNC="binlog_after_log_and_order SIGNAL c2_committed";
COMMIT;
# Connection c1
# This should warn about DEBUG_SYNC timeout
Warnings:
Warning 1639 debug sync point wait timed out
# Connection c2
SHOW BINLOG EVENTS LIMIT 2,12;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 174 Query 1 265 use `test`; UPDATE t1 SET a=10 WHERE k=1
master-bin.000001 265 Xid 1 292 COMMIT /* xid=XX */
master-bin.000001 292 Query 1 360 BEGIN
master-bin.000001 360 Query 1 451 use `test`; UPDATE t1 SET a=20 WHERE k=1
master-bin.000001 451 Xid 1 478 COMMIT /* xid=XX */
master-bin.000001 478 Query 1 546 BEGIN
master-bin.000001 546 Query 1 637 use `test`; UPDATE t1 SET a=10 WHERE k=2
master-bin.000001 637 Xid 1 664 COMMIT /* xid=XX */
master-bin.000001 664 Query 1 732 BEGIN
master-bin.000001 732 Query 1 823 use `test`; UPDATE t1 SET a=20 WHERE k=2
master-bin.000001 823 Xid 1 850 COMMIT /* xid=XX */
# Connection c1
RESET MASTER;
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing";
UPDATE t1 SET a=10 WHERE k=3;
# Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
SELECT * FROM t1 WHERE k=3 FOR UPDATE;
k a b c
3 10 0 0
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c2_committing";
UPDATE t1 SET a=20 WHERE k=3;
# Connection c1
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2";
UPDATE t1 SET a=10 WHERE k=4;
# Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
SELECT * FROM t1 WHERE k=4 FOR UPDATE;
k a b c
4 10 0 0
SET DEBUG_SYNC="binlog_after_log_and_order SIGNAL c2_committed";
UPDATE t1 SET a=20 WHERE k=4;
# Connection c1
# This should warn about DEBUG_SYNC timeout
Warnings:
Warning 1639 debug sync point wait timed out
# Connection c2
SHOW BINLOG EVENTS LIMIT 1,12;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 106 Query 1 174 BEGIN
master-bin.000001 174 Query 1 265 use `test`; UPDATE t1 SET a=10 WHERE k=3
master-bin.000001 265 Xid 1 292 COMMIT /* xid=XX */
master-bin.000001 292 Query 1 360 BEGIN
master-bin.000001 360 Query 1 451 use `test`; UPDATE t1 SET a=20 WHERE k=3
master-bin.000001 451 Xid 1 478 COMMIT /* xid=XX */
master-bin.000001 478 Query 1 546 BEGIN
master-bin.000001 546 Query 1 637 use `test`; UPDATE t1 SET a=10 WHERE k=4
master-bin.000001 637 Xid 1 664 COMMIT /* xid=XX */
master-bin.000001 664 Query 1 732 BEGIN
master-bin.000001 732 Query 1 823 use `test`; UPDATE t1 SET a=20 WHERE k=4
master-bin.000001 823 Xid 1 850 COMMIT /* xid=XX */
SELECT * FROM t1 ORDER BY k;
k a b c
1 20 0 0
2 20 0 0
3 20 0 0
4 20 0 0
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';
mysql-test/t/innodb_release_row_locks_early-master.opt
0 → 100644
View file @
acd695d8
--innodb-release-locks-early=1
mysql-test/t/innodb_release_row_locks_early.test
0 → 100644
View file @
acd695d8
--
source
include
/
have_debug_sync
.
inc
--
source
include
/
have_innodb
.
inc
--
source
include
/
have_log_bin
.
inc
--
disable_warnings
DROP
TABLE
IF
EXISTS
t1
;
--
enable_warnings
CREATE
TABLE
t1
(
k
INT
NOT
NULL
,
a
INT
NOT
NULL
,
b
INT
NOT
NULL
,
c
INT
NOT
NULL
,
PRIMARY
KEY
(
k
))
ENGINE
=
InnoDB
;
INSERT
INTO
t1
(
k
,
a
,
b
,
c
)
VALUES
(
1
,
0
,
0
,
0
);
INSERT
INTO
t1
(
k
,
a
,
b
,
c
)
VALUES
(
2
,
0
,
0
,
0
);
INSERT
INTO
t1
(
k
,
a
,
b
,
c
)
VALUES
(
3
,
0
,
0
,
0
);
INSERT
INTO
t1
(
k
,
a
,
b
,
c
)
VALUES
(
4
,
0
,
0
,
0
);
RESET
MASTER
;
SET
DEBUG_SYNC
=
'RESET'
;
# Two transactions A,B that update the same row.
# A releases row locks during the prepare phase, and waits using DEBUG_SYNC.
# B then updates the same row.
# Verify that
# - B's update can proceed while A is waiting for commit, showing that
# locks are released early.
# - B cannot be binlogged before A.
connect
(
c1
,
127.0
.
0.1
,
root
,,
test
,
$MASTER_MYPORT
,);
connect
(
c2
,
127.0
.
0.1
,
root
,,
test
,
$MASTER_MYPORT
,);
connection
c1
;
--
echo
# Connection c1
# First verify that row locks are released early.
BEGIN
;
UPDATE
t1
SET
a
=
10
WHERE
k
=
1
;
# Wait until c2 starts COMMIT, to verify that we release our locks in prepare.
SET
DEBUG_SYNC
=
"commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing"
;
send
COMMIT
;
connection
c2
;
--
echo
# Connection c2
SET
DEBUG_SYNC
=
"now WAIT_FOR c1_prepared"
;
BEGIN
;
SELECT
*
FROM
t1
WHERE
k
=
1
FOR
UPDATE
;
UPDATE
t1
SET
a
=
20
WHERE
k
=
1
;
SET
DEBUG_SYNC
=
"now SIGNAL c2_committing"
;
COMMIT
;
connection
c1
;
--
echo
# Connection c1
reap
;
# Now verify that binlog order is correct.
BEGIN
;
UPDATE
t1
SET
a
=
10
WHERE
k
=
2
;
# This time wait until c2 is binlogged. This should time out, as we must not
# allow c2 to finish commit before c1.
SET
DEBUG_SYNC
=
"commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2"
;
send
COMMIT
;
connection
c2
;
--
echo
# Connection c2
SET
DEBUG_SYNC
=
"now WAIT_FOR c1_prepared"
;
BEGIN
;
SELECT
*
FROM
t1
WHERE
k
=
2
FOR
UPDATE
;
UPDATE
t1
SET
a
=
20
WHERE
k
=
2
;
SET
DEBUG_SYNC
=
"binlog_after_log_and_order SIGNAL c2_committed"
;
send
COMMIT
;
connection
c1
;
--
echo
# Connection c1
--
echo
# This should warn about DEBUG_SYNC timeout
reap
;
connection
c2
;
--
echo
# Connection c2
reap
;
--
replace_regex
/
xid
=
[
0
-
9
]
+/
xid
=
XX
/
SHOW
BINLOG
EVENTS
LIMIT
2
,
12
;
connection
c1
;
--
echo
# Connection c1
# Now the same thing, but using autocommit.
RESET
MASTER
;
# First verify that row locks are released early.
# Wait until c2 starts COMMIT, to verify that we release our locks in prepare.
SET
DEBUG_SYNC
=
"commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing"
;
send
UPDATE
t1
SET
a
=
10
WHERE
k
=
3
;
connection
c2
;
--
echo
# Connection c2
SET
DEBUG_SYNC
=
"now WAIT_FOR c1_prepared"
;
SELECT
*
FROM
t1
WHERE
k
=
3
FOR
UPDATE
;
SET
DEBUG_SYNC
=
"commit_after_release_LOCK_prepare_ordered SIGNAL c2_committing"
;
UPDATE
t1
SET
a
=
20
WHERE
k
=
3
;
connection
c1
;
--
echo
# Connection c1
reap
;
# Now verify that binlog order is correct, this time with autocommit.
# This time wait until c2 is binlogged. This should time out, as we must not
# allow c2 to finish commit before c1.
SET
DEBUG_SYNC
=
"commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2"
;
send
UPDATE
t1
SET
a
=
10
WHERE
k
=
4
;
connection
c2
;
--
echo
# Connection c2
SET
DEBUG_SYNC
=
"now WAIT_FOR c1_prepared"
;
SELECT
*
FROM
t1
WHERE
k
=
4
FOR
UPDATE
;
SET
DEBUG_SYNC
=
"binlog_after_log_and_order SIGNAL c2_committed"
;
send
UPDATE
t1
SET
a
=
20
WHERE
k
=
4
;
connection
c1
;
--
echo
# Connection c1
--
echo
# This should warn about DEBUG_SYNC timeout
reap
;
connection
c2
;
--
echo
# Connection c2
reap
;
--
replace_regex
/
xid
=
[
0
-
9
]
+/
xid
=
XX
/
SHOW
BINLOG
EVENTS
LIMIT
1
,
12
;
SELECT
*
FROM
t1
ORDER
BY
k
;
DROP
TABLE
t1
;
SET
DEBUG_SYNC
=
'RESET'
;
sql/log.cc
View file @
acd695d8
...
...
@@ -4991,6 +4991,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
DEBUG_SYNC
(
entry
->
thd
,
"commit_after_prepare_ordered"
);
}
pthread_mutex_unlock
(
&
LOCK_prepare_ordered
);
DEBUG_SYNC
(
entry
->
thd
,
"commit_after_release_LOCK_prepare_ordered"
);
/*
The first in the queue handle group commit for all; the others just wait
...
...
@@ -6499,6 +6500,8 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
else
err
=
binlog_flush_trx_cache
(
thd
,
trx_data
,
NULL
,
all
);
DEBUG_SYNC
(
thd
,
"binlog_after_log_and_order"
);
DBUG_RETURN
(
!
err
);
}
...
...
storage/xtradb/handler/ha_innodb.cc
View file @
acd695d8
...
...
@@ -220,6 +220,7 @@ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
static
INNOBASE_SHARE
*
get_share
(
const
char
*
table_name
);
static
void
free_share
(
INNOBASE_SHARE
*
share
);
static
int
innobase_close_connection
(
handlerton
*
hton
,
THD
*
thd
);
static
void
innobase_prepare_ordered
(
handlerton
*
hton
,
THD
*
thd
,
bool
all
);
static
void
innobase_commit_ordered
(
handlerton
*
hton
,
THD
*
thd
,
bool
all
);
static
int
innobase_commit
(
handlerton
*
hton
,
THD
*
thd
,
bool
all
);
static
int
innobase_rollback
(
handlerton
*
hton
,
THD
*
thd
,
bool
all
);
...
...
@@ -2041,6 +2042,10 @@ innobase_init(
innobase_hton
->
savepoint_set
=
innobase_savepoint
;
innobase_hton
->
savepoint_rollback
=
innobase_rollback_to_savepoint
;
innobase_hton
->
savepoint_release
=
innobase_release_savepoint
;
if
(
innobase_release_locks_early
)
innobase_hton
->
prepare_ordered
=
innobase_prepare_ordered
;
else
innobase_hton
->
prepare_ordered
=
NULL
;
innobase_hton
->
commit_ordered
=
innobase_commit_ordered
;
innobase_hton
->
commit
=
innobase_commit
;
innobase_hton
->
rollback
=
innobase_rollback
;
...
...
@@ -2726,6 +2731,54 @@ innobase_start_trx_and_assign_read_view(
DBUG_RETURN
(
0
);
}
/*****************************************************************//**
Release row locks early during prepare phase.
Only enabled if --innodb-release-locks-early=1. In this case, a prepared
transaction is treated as committed to memory (but not to disk), and we
release row locks at the end of the prepare phase.
The consistent commit ordering guarantees of prepare_ordered() calls means
that transactions will not be binlogged in different order than locks are
released (which would cause trouble for statement-based replication).
This optimisation is not 100% safe, so is not enabled by default. But some
applications may decide to enable it to reduce contention on hotspot rows.
The consequences of enabling this are:
- It is not possible to rollback after successful prepare(). If there is
a need to rollback (ie. failure to binlog the transaction), we crash the
server (!)
- If we crash during commit, it is possible that an application/user can have
seen another transaction committed that is not recovered by XA crash
recovery. Thus durability is partially lost. However, consistency is still
guaranteed, we never recover a transaction and not recover another
transaction that committed before. */
static
void
innobase_prepare_ordered
(
/*============*/
handlerton
*
hton
,
/*!< in: Innodb handlerton */
THD
*
thd
,
/*!< in: MySQL thread handle of the user for whom
the transaction should be committed */
bool
all
)
/*!< in: TRUE - commit transaction
FALSE - the current SQL statement ended */
{
trx_t
*
trx
;
DBUG_ENTER
(
"innobase_prepare_ordered"
);
DBUG_ASSERT
(
hton
==
innodb_hton_ptr
);
trx
=
check_trx_exists
(
thd
);
mutex_enter
(
&
kernel_mutex
);
lock_release_off_kernel
(
trx
);
mutex_exit
(
&
kernel_mutex
);
DBUG_VOID_RETURN
;
}
static
void
innobase_commit_ordered_2
(
...
...
@@ -2966,6 +3019,15 @@ innobase_rollback(
row_unlock_table_autoinc_for_mysql
(
trx
);
/* if transaction has already released locks, it is too late to
rollback */
if
(
innobase_release_locks_early
&&
trx
->
conc_state
==
TRX_PREPARED
&&
UT_LIST_GET_LEN
(
trx
->
trx_locks
)
==
0
)
{
sql_print_error
(
"Rollback after releasing locks! "
"errno=%d, dberr=%d"
,
errno
,
trx
->
error_state
);
ut_error
;
}
if
(
all
||
!
thd_test_options
(
thd
,
OPTION_NOT_AUTOCOMMIT
|
OPTION_BEGIN
))
{
...
...
@@ -11691,6 +11753,11 @@ static MYSQL_SYSVAR_ULINT(pass_corrupt_table, srv_pass_corrupt_table,
"except for the deletion."
,
NULL
,
NULL
,
0
,
0
,
1
,
0
);
static
MYSQL_SYSVAR_BOOL
(
release_locks_early
,
innobase_release_locks_early
,
PLUGIN_VAR_READONLY
,
"Release row locks in the prepare stage instead of in the commit stage"
,
NULL
,
NULL
,
FALSE
);
static
struct
st_mysql_sys_var
*
innobase_system_variables
[]
=
{
MYSQL_SYSVAR
(
page_size
),
MYSQL_SYSVAR
(
additional_mem_pool_size
),
...
...
@@ -11778,6 +11845,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR
(
auto_lru_dump
),
MYSQL_SYSVAR
(
use_purge_thread
),
MYSQL_SYSVAR
(
pass_corrupt_table
),
MYSQL_SYSVAR
(
release_locks_early
),
NULL
};
...
...
storage/xtradb/include/srv0srv.h
View file @
acd695d8
...
...
@@ -344,6 +344,9 @@ extern ulint srv_buf_pool_reads;
/** Time in seconds between automatic buffer pool dumps */
extern
uint
srv_auto_lru_dump
;
/** Release row locks already in the prepare phase */
extern
my_bool
innobase_release_locks_early
;
/** Status variables to be passed to MySQL */
typedef
struct
export_var_struct
export_struc
;
...
...
storage/xtradb/include/trx0sys.ic
View file @
acd695d8
...
...
@@ -338,6 +338,12 @@ trx_list_get_min_trx_id(void)
/****************************************************************//**
Checks if a transaction with the given id is active.
IMPORTANT ASSUMPTION:
It is assumed that this function is only used for the purpose of
determining if locks need to be created for the input transaction.
So if innobase_release_locks_early global option is set, and if
the transaction is already in prepared state, this returns FALSE,
as locks are no longer needed for the transaction.
@return TRUE if active */
UNIV_INLINE
ibool
...
...
@@ -366,7 +372,8 @@ trx_is_active(
trx = trx_get_on_id(trx_id);
if (trx && (trx->conc_state == TRX_ACTIVE
|| trx->conc_state == TRX_PREPARED)) {
|| (trx->conc_state == TRX_PREPARED &&
!innobase_release_locks_early))) {
return(TRUE);
}
...
...
storage/xtradb/srv/srv0srv.c
View file @
acd695d8
...
...
@@ -482,6 +482,9 @@ UNIV_INTERN FILE* srv_misc_tmpfile;
UNIV_INTERN
ulint
srv_main_thread_process_no
=
0
;
UNIV_INTERN
ulint
srv_main_thread_id
=
0
;
/* Release row locks already in the prepare phase */
UNIV_INTERN
my_bool
innobase_release_locks_early
=
FALSE
;
/* The following count work done by srv_master_thread. */
/* Iterations by the 'once per second' loop. */
...
...
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