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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
a35a93aa
Commit
a35a93aa
authored
Nov 30, 2004
by
marko@hundin.mysql.fi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
InnoDB: Allow ALTER TABLE to do intermediate COMMIT also when the table
contains auto_increment columns. (Bug #6633)
parent
2e7cb4d0
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
162 additions
and
61 deletions
+162
-61
innobase/include/lock0lock.h
innobase/include/lock0lock.h
+24
-9
innobase/lock/lock0lock.c
innobase/lock/lock0lock.c
+111
-28
sql/ha_innodb.cc
sql/ha_innodb.cc
+27
-24
No files found.
innobase/include/lock0lock.h
View file @
a35a93aa
...
...
@@ -463,17 +463,32 @@ lock_rec_hash(
ulint
space
,
/* in: space */
ulint
page_no
);
/* in: page number */
/*************************************************************************
Gets the
table covered by an IX or IS table lock, if there are no
other locks on the table
. */
Gets the
source table of an ALTER TABLE transaction. The table must be
covered by an IX or IS table lock
. */
dict_table_t
*
lock_get_table
(
/*===========*/
/* out: the table covered by the lock,
or NULL if it is not an IX or IS table lock,
or there are other locks on the table */
lock_t
*
lock
,
/* in: lock */
ulint
*
mode
);
/* out: lock mode of table */
lock_get_src_table
(
/*===============*/
/* out: the source table of transaction,
if it is covered by an IX or IS table lock;
dest if there is no source table, and
NULL if the transaction is locking more than
two tables or an inconsistency is found */
trx_t
*
trx
,
/* in: transaction */
dict_table_t
*
dest
,
/* in: destination of ALTER TABLE */
ulint
*
mode
);
/* out: lock mode of the source table */
/*************************************************************************
Determine if the given table is exclusively "owned" by the given
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
on the table. */
ibool
lock_table_exclusive
(
/*=================*/
/* out: TRUE if table is only locked by trx,
with LOCK_IX, and possibly LOCK_AUTO_INC */
dict_table_t
*
table
,
/* in: table */
trx_t
*
trx
);
/* in: transaction */
/*************************************************************************
Checks that a transaction id is sensible, i.e., not in the future. */
...
...
innobase/lock/lock0lock.c
View file @
a35a93aa
...
...
@@ -602,42 +602,125 @@ lock_get_wait(
}
/*************************************************************************
Gets the
table covered by an IX or IS table lock, if there are no
other locks on the table
. */
Gets the
source table of an ALTER TABLE transaction. The table must be
covered by an IX or IS table lock
. */
dict_table_t
*
lock_get_table
(
/*===========*/
/* out: the table covered by the lock,
or NULL if it is not an IX or IS table lock,
or there are other locks on the table */
lock_t
*
lock
,
/* in: lock */
ulint
*
mode
)
/* out: lock mode of table */
lock_get_src_table
(
/*===============*/
/* out: the source table of transaction,
if it is covered by an IX or IS table lock;
dest if there is no source table, and
NULL if the transaction is locking more than
two tables or an inconsistency is found */
trx_t
*
trx
,
/* in: transaction */
dict_table_t
*
dest
,
/* in: destination of ALTER TABLE */
ulint
*
mode
)
/* out: lock mode of the source table */
{
dict_table_t
*
table
;
ulint
lock_mode
;
dict_table_t
*
src
;
lock_t
*
lock
;
table
=
NULL
;
src
=
NULL
;
*
mode
=
LOCK_NONE
;
if
(
lock_get_type
(
lock
)
!=
LOCK_TABLE
)
{
return
(
table
);
}
lock_mode
=
lock_get_mode
(
lock
);
switch
(
lock_mode
)
{
case
LOCK_IS
:
case
LOCK_IX
:
*
mode
=
lock_mode
;
table
=
lock
->
un_member
.
tab_lock
.
table
;
if
(
UT_LIST_GET_LEN
(
table
->
locks
)
!=
1
||
UT_LIST_GET_FIRST
(
table
->
locks
)
!=
lock
)
{
/* We only support the case when
there is only one lock on this table. */
table
=
NULL
;
for
(
lock
=
UT_LIST_GET_FIRST
(
trx
->
trx_locks
);
lock
;
lock
=
UT_LIST_GET_NEXT
(
trx_locks
,
lock
))
{
lock_table_t
*
tab_lock
;
ulint
lock_mode
;
if
(
!
(
lock_get_type
(
lock
)
&
LOCK_TABLE
))
{
/* We are only interested in table locks. */
continue
;
}
tab_lock
=
&
lock
->
un_member
.
tab_lock
;
if
(
dest
==
tab_lock
->
table
)
{
/* We are not interested in the destination table. */
continue
;
}
else
if
(
!
src
)
{
/* This presumably is the source table. */
src
=
tab_lock
->
table
;
if
(
UT_LIST_GET_LEN
(
src
->
locks
)
!=
1
||
UT_LIST_GET_FIRST
(
src
->
locks
)
!=
lock
)
{
/* We only support the case when
there is only one lock on this table. */
return
(
NULL
);
}
}
else
if
(
src
!=
tab_lock
->
table
)
{
/* The transaction is locking more than
two tables (src and dest): abort */
return
(
NULL
);
}
/* Check that the source table is locked by
LOCK_IX or LOCK_IS. */
lock_mode
=
lock_get_mode
(
lock
);
switch
(
lock_mode
)
{
case
LOCK_IX
:
case
LOCK_IS
:
if
(
*
mode
!=
LOCK_NONE
&&
*
mode
!=
lock_mode
)
{
/* There are multiple locks on src. */
return
(
NULL
);
}
*
mode
=
lock_mode
;
break
;
}
}
return
(
table
);
if
(
!
src
)
{
/* No source table lock found: flag the situation to caller */
src
=
dest
;
}
return
(
src
);
}
/*************************************************************************
Determine if the given table is exclusively "owned" by the given
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
on the table. */
ibool
lock_is_table_exclusive
(
/*====================*/
/* out: TRUE if table is only locked by trx,
with LOCK_IX, and possibly LOCK_AUTO_INC */
dict_table_t
*
table
,
/* in: table */
trx_t
*
trx
)
/* in: transaction */
{
lock_t
*
lock
;
bool
ok
=
FALSE
;
ut_ad
(
table
&&
trx
);
for
(
lock
=
UT_LIST_GET_FIRST
(
table
->
locks
);
lock
;
lock
=
UT_LIST_GET_NEXT
(
locks
,
&
lock
->
un_member
.
tab_lock
))
{
if
(
lock
->
trx
!=
trx
)
{
/* A lock on the table is held
by some other transaction. */
return
(
FALSE
);
}
if
(
!
(
lock_get_type
(
lock
)
&
LOCK_TABLE
))
{
/* We are interested in table locks only. */
continue
;
}
switch
(
lock_get_mode
(
lock
))
{
case
LOCK_IX
:
ok
=
TRUE
;
break
;
case
LOCK_AUTO_INC
:
/* It is allowed for trx to hold an
auto_increment lock. */
break
;
default:
/* Other table locks than LOCK_IX are not allowed. */
return
(
FALSE
);
}
}
return
(
ok
);
}
/*************************************************************************
...
...
sql/ha_innodb.cc
View file @
a35a93aa
...
...
@@ -2325,29 +2325,44 @@ ha_innobase::write_row(
intermediate COMMIT, since writes by other transactions are
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
dict_table_t
*
table
;
dict_table_t
*
src_
table
;
ibool
mode
;
num_write_row
=
0
;
/* Commit the transaction. This will release the table
locks, so they have to be acquired again. */
switch
(
prebuilt
->
trx
->
mysql_n_tables_locked
)
{
case
1
:
/* Altering an InnoDB table */
/* Get the source table. */
src_table
=
lock_get_src_table
(
prebuilt
->
trx
,
prebuilt
->
table
,
&
mode
);
if
(
!
src_table
)
{
no_commit:
/* Unknown situation: do not commit */
/*
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB error: ALTER TABLE is holding lock"
" on %lu tables!\n",
prebuilt->trx->mysql_n_tables_locked);
*/
;
}
else
if
(
src_table
==
prebuilt
->
table
)
{
/* Source table is not in InnoDB format:
no need to re-acquire locks on it. */
/* Altering to InnoDB format */
innobase_commit
(
user_thd
,
prebuilt
->
trx
);
/* Note that this transaction is still active. */
user_thd
->
transaction
.
all
.
innodb_active_trans
=
1
;
/* We will need an IX lock on the destination table. */
prebuilt
->
sql_stat_start
=
TRUE
;
break
;
case
2
:
/* Altering an InnoDB table */
ut_a
(
UT_LIST_GET_LEN
(
prebuilt
->
trx
->
trx_locks
)
>=
2
);
table
=
lock_get_table
(
UT_LIST_GET_FIRST
(
prebuilt
->
trx
->
trx_locks
),
&
mode
);
if
(
!
table
)
{
}
else
{
/* Ensure that there are no other table locks than
LOCK_IX and LOCK_AUTO_INC on the destination table. */
if
(
!
lock_is_table_exclusive
(
prebuilt
->
table
,
prebuilt
->
trx
))
{
goto
no_commit
;
}
...
...
@@ -2357,21 +2372,9 @@ ha_innobase::write_row(
/* Note that this transaction is still active. */
user_thd
->
transaction
.
all
.
innodb_active_trans
=
1
;
/* Re-acquire the table lock on the source table. */
row_lock_table_for_mysql
(
prebuilt
,
table
,
mode
);
row_lock_table_for_mysql
(
prebuilt
,
src_
table
,
mode
);
/* We will need an IX lock on the destination table. */
prebuilt
->
sql_stat_start
=
TRUE
;
break
;
default:
no_commit:
/* Unknown situation: do nothing (no commit) */
/*
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB error: ALTER TABLE is holding lock"
" on %lu tables!\n",
prebuilt->trx->mysql_n_tables_locked);
*/
break
;
}
}
...
...
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