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
8ab135a7
Commit
8ab135a7
authored
May 03, 2004
by
marko@hundin.mysql.fi
Browse files
Options
Browse Files
Download
Plain Diff
Merge marko@build.mysql.com:/home/bk/mysql-4.0
into hundin.mysql.fi:/home/marko/l/mysql-4.0
parents
d9bed749
a490b95b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
323 additions
and
20 deletions
+323
-20
innobase/include/lock0lock.h
innobase/include/lock0lock.h
+20
-1
innobase/include/row0mysql.h
innobase/include/row0mysql.h
+16
-0
innobase/include/trx0trx.h
innobase/include/trx0trx.h
+2
-0
innobase/lock/lock0lock.c
innobase/lock/lock0lock.c
+118
-12
innobase/row/row0mysql.c
innobase/row/row0mysql.c
+86
-2
innobase/trx/trx0trx.c
innobase/trx/trx0trx.c
+2
-0
mysql-test/r/innodb-lock.result
mysql-test/r/innodb-lock.result
+22
-0
mysql-test/r/innodb.result
mysql-test/r/innodb.result
+1
-1
mysql-test/t/innodb-lock.test
mysql-test/t/innodb-lock.test
+40
-0
sql/ha_innodb.cc
sql/ha_innodb.cc
+16
-4
No files found.
innobase/include/lock0lock.h
View file @
8ab135a7
...
...
@@ -381,7 +381,9 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint
flags
,
/* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
does nothing;
if LOCK_TABLE_EXP bits are set,
creates an explicit table lock */
dict_table_t
*
table
,
/* in: database table in dictionary cache */
ulint
mode
,
/* in: lock mode */
que_thr_t
*
thr
);
/* in: query thread */
...
...
@@ -394,6 +396,14 @@ lock_is_on_table(
/* out: TRUE if there are lock(s) */
dict_table_t
*
table
);
/* in: database table in dictionary cache */
/*************************************************************************
Releases a table lock.
Releases possible other transactions waiting for this lock. */
void
lock_table_unlock
(
/*==============*/
lock_t
*
lock
);
/* in: lock */
/*************************************************************************
Releases an auto-inc lock a transaction possibly has on a table.
Releases possible other transactions waiting for this lock. */
...
...
@@ -410,6 +420,14 @@ lock_release_off_kernel(
/*====================*/
trx_t
*
trx
);
/* in: transaction */
/*************************************************************************
Releases table locks, and releases possible other transactions waiting
because of these locks. */
void
lock_release_tables_off_kernel
(
/*===========================*/
trx_t
*
trx
);
/* in: transaction */
/*************************************************************************
Cancels a waiting lock request and releases possible other transactions
waiting behind it. */
...
...
@@ -536,6 +554,7 @@ extern lock_sys_t* lock_sys;
/* Lock types */
#define LOCK_TABLE 16
/* these type values should be so high that */
#define LOCK_REC 32
/* they can be ORed to the lock mode */
#define LOCK_TABLE_EXP 80
/* explicit table lock */
#define LOCK_TYPE_MASK 0xF0UL
/* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
...
...
innobase/include/row0mysql.h
View file @
8ab135a7
...
...
@@ -153,6 +153,22 @@ row_lock_table_autoinc_for_mysql(
row_prebuilt_t
*
prebuilt
);
/* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
Unlocks a table lock possibly reserved by trx. */
void
row_unlock_table_for_mysql
(
/*=======================*/
trx_t
*
trx
);
/* in: transaction */
/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
row_lock_table_for_mysql
(
/*=====================*/
/* out: error code or DB_SUCCESS */
row_prebuilt_t
*
prebuilt
);
/* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
Does an insert for MySQL. */
int
...
...
innobase/include/trx0trx.h
View file @
8ab135a7
...
...
@@ -421,6 +421,8 @@ struct trx_struct{
lock_t
*
auto_inc_lock
;
/* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
ulint
n_tables_locked
;
/* number of table locks reserved by
the transaction, stored in trx_locks */
UT_LIST_NODE_T
(
trx_t
)
trx_list
;
/* list of transactions */
UT_LIST_NODE_T
(
trx_t
)
...
...
innobase/lock/lock0lock.c
View file @
8ab135a7
...
...
@@ -2001,7 +2001,11 @@ lock_grant(
release it at the end of the SQL statement */
lock
->
trx
->
auto_inc_lock
=
lock
;
}
}
else
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE_EXP
)
{
ut_ad
(
lock_get_mode
(
lock
)
==
LOCK_S
||
lock_get_mode
(
lock
)
==
LOCK_X
);
lock
->
trx
->
n_tables_locked
++
;
}
#ifdef UNIV_DEBUG
if
(
lock_print_waits
)
{
...
...
@@ -2939,7 +2943,7 @@ lock_deadlock_occurs(
}
if
(
ret
==
LOCK_VICTIM_IS_START
)
{
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE
)
{
if
(
lock_get_type
(
lock
)
&
LOCK_TABLE
)
{
table
=
lock
->
un_member
.
tab_lock
.
table
;
index
=
NULL
;
}
else
{
...
...
@@ -3015,7 +3019,7 @@ lock_deadlock_recursive(
/* Look at the locks ahead of wait_lock in the lock queue */
for
(;;)
{
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE
)
{
if
(
lock_get_type
(
lock
)
&
LOCK_TABLE
)
{
lock
=
UT_LIST_GET_PREV
(
un_member
.
tab_lock
.
locks
,
lock
);
}
else
{
...
...
@@ -3347,7 +3351,9 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint
flags
,
/* in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
does nothing;
if LOCK_TABLE_EXP bits are set,
creates an explicit table lock */
dict_table_t
*
table
,
/* in: database table in dictionary cache */
ulint
mode
,
/* in: lock mode */
que_thr_t
*
thr
)
/* in: query thread */
...
...
@@ -3362,6 +3368,8 @@ lock_table(
return
(
DB_SUCCESS
);
}
ut_ad
(
flags
==
0
||
flags
==
LOCK_TABLE_EXP
);
trx
=
thr_get_trx
(
thr
);
lock_mutex_enter_kernel
();
...
...
@@ -3390,7 +3398,12 @@ lock_table(
return
(
err
);
}
lock_table_create
(
table
,
mode
,
trx
);
lock_table_create
(
table
,
mode
|
flags
,
trx
);
if
(
flags
)
{
ut_ad
(
mode
==
LOCK_S
||
mode
==
LOCK_X
);
trx
->
n_tables_locked
++
;
}
lock_mutex_exit_kernel
();
...
...
@@ -3471,7 +3484,8 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad
(
mutex_own
(
&
kernel_mutex
));
#endif
/* UNIV_SYNC_DEBUG */
ut_ad
(
lock_get_type
(
in_lock
)
==
LOCK_TABLE
);
ut_ad
(
lock_get_type
(
in_lock
)
==
LOCK_TABLE
||
lock_get_type
(
in_lock
)
==
LOCK_TABLE_EXP
);
lock
=
UT_LIST_GET_NEXT
(
un_member
.
tab_lock
.
locks
,
in_lock
);
...
...
@@ -3495,6 +3509,22 @@ lock_table_dequeue(
/*=========================== LOCK RELEASE ==============================*/
/*************************************************************************
Releases a table lock.
Releases possible other transactions waiting for this lock. */
void
lock_table_unlock
(
/*==============*/
lock_t
*
lock
)
/* in: lock */
{
mutex_enter
(
&
kernel_mutex
);
lock_table_dequeue
(
lock
);
mutex_exit
(
&
kernel_mutex
);
}
/*************************************************************************
Releases an auto-inc lock a transaction possibly has on a table.
Releases possible other transactions waiting for this lock. */
...
...
@@ -3542,7 +3572,7 @@ lock_release_off_kernel(
lock_rec_dequeue_from_page
(
lock
);
}
else
{
ut_ad
(
lock_get_type
(
lock
)
==
LOCK_TABLE
);
ut_ad
(
lock_get_type
(
lock
)
&
LOCK_TABLE
);
if
(
lock_get_mode
(
lock
)
!=
LOCK_IS
&&
(
trx
->
insert_undo
||
trx
->
update_undo
))
{
...
...
@@ -3558,6 +3588,11 @@ lock_release_off_kernel(
}
lock_table_dequeue
(
lock
);
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE_EXP
)
{
ut_ad
(
lock_get_mode
(
lock
)
==
LOCK_S
||
lock_get_mode
(
lock
)
==
LOCK_X
);
trx
->
n_tables_locked
--
;
}
}
if
(
count
==
LOCK_RELEASE_KERNEL_INTERVAL
)
{
...
...
@@ -3577,6 +3612,73 @@ lock_release_off_kernel(
mem_heap_empty
(
trx
->
lock_heap
);
ut_a
(
trx
->
auto_inc_lock
==
NULL
);
ut_a
(
trx
->
n_tables_locked
==
0
);
}
/*************************************************************************
Releases table locks, and releases possible other transactions waiting
because of these locks. */
void
lock_release_tables_off_kernel
(
/*===========================*/
trx_t
*
trx
)
/* in: transaction */
{
dict_table_t
*
table
;
ulint
count
;
lock_t
*
lock
;
#ifdef UNIV_SYNC_DEBUG
ut_ad
(
mutex_own
(
&
kernel_mutex
));
#endif
/* UNIV_SYNC_DEBUG */
lock
=
UT_LIST_GET_LAST
(
trx
->
trx_locks
);
count
=
0
;
while
(
lock
!=
NULL
)
{
count
++
;
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE_EXP
)
{
ut_ad
(
lock_get_mode
(
lock
)
==
LOCK_S
||
lock_get_mode
(
lock
)
==
LOCK_X
);
if
(
trx
->
insert_undo
||
trx
->
update_undo
)
{
/* The trx may have modified the table.
We block the use of the MySQL query
cache for all currently active
transactions. */
table
=
lock
->
un_member
.
tab_lock
.
table
;
table
->
query_cache_inv_trx_id
=
trx_sys
->
max_trx_id
;
}
lock_table_dequeue
(
lock
);
trx
->
n_tables_locked
--
;
lock
=
UT_LIST_GET_LAST
(
trx
->
trx_locks
);
continue
;
}
if
(
count
==
LOCK_RELEASE_KERNEL_INTERVAL
)
{
/* Release the kernel mutex for a while, so that we
do not monopolize it */
lock_mutex_exit_kernel
();
lock_mutex_enter_kernel
();
count
=
0
;
}
lock
=
UT_LIST_GET_PREV
(
trx_locks
,
lock
);
}
mem_heap_empty
(
trx
->
lock_heap
);
ut_a
(
trx
->
n_tables_locked
==
0
);
}
/*************************************************************************
...
...
@@ -3596,7 +3698,7 @@ lock_cancel_waiting_and_release(
lock_rec_dequeue_from_page
(
lock
);
}
else
{
ut_ad
(
lock_get_type
(
lock
)
==
LOCK_TABLE
);
ut_ad
(
lock_get_type
(
lock
)
&
LOCK_TABLE
);
lock_table_dequeue
(
lock
);
}
...
...
@@ -3637,7 +3739,7 @@ lock_reset_all_on_table_for_trx(
ut_a
(
!
lock_get_wait
(
lock
));
lock_rec_discard
(
lock
);
}
else
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE
}
else
if
(
lock_get_type
(
lock
)
&
LOCK_TABLE
&&
lock
->
un_member
.
tab_lock
.
table
==
table
)
{
ut_a
(
!
lock_get_wait
(
lock
));
...
...
@@ -3689,8 +3791,12 @@ lock_table_print(
#ifdef UNIV_SYNC_DEBUG
ut_ad
(
mutex_own
(
&
kernel_mutex
));
#endif
/* UNIV_SYNC_DEBUG */
ut_a
(
lock_get_type
(
lock
)
==
LOCK_TABLE
);
ut_a
(
lock_get_type
(
lock
)
==
LOCK_TABLE
||
lock_get_type
(
lock
)
==
LOCK_TABLE_EXP
);
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE_EXP
)
{
fputs
(
"EXPLICIT "
,
file
);
}
fputs
(
"TABLE LOCK table "
,
file
);
ut_print_name
(
file
,
lock
->
un_member
.
tab_lock
.
table
->
name
);
fprintf
(
file
,
" trx id %lu %lu"
,
...
...
@@ -4009,7 +4115,7 @@ lock_print_info(
lock_rec_print
(
file
,
lock
);
}
else
{
ut_ad
(
lock_get_type
(
lock
)
==
LOCK_TABLE
);
ut_ad
(
lock_get_type
(
lock
)
&
LOCK_TABLE
);
lock_table_print
(
file
,
lock
);
}
...
...
@@ -4290,7 +4396,7 @@ lock_validate(void)
lock
=
UT_LIST_GET_FIRST
(
trx
->
trx_locks
);
while
(
lock
)
{
if
(
lock_get_type
(
lock
)
==
LOCK_TABLE
)
{
if
(
lock_get_type
(
lock
)
&
LOCK_TABLE
)
{
lock_table_queue_validate
(
lock
->
un_member
.
tab_lock
.
table
);
...
...
innobase/row/row0mysql.c
View file @
8ab135a7
...
...
@@ -693,10 +693,94 @@ row_lock_table_autoinc_for_mysql(
/* It may be that the current session has not yet started
its transaction, or it has been committed: */
trx_start_if_not_started
(
trx
);
err
=
lock_table
(
0
,
prebuilt
->
table
,
prebuilt
->
select_lock_type
,
thr
);
trx
->
error_state
=
err
;
if
(
err
!=
DB_SUCCESS
)
{
que_thr_stop_for_mysql
(
thr
);
was_lock_wait
=
row_mysql_handle_errors
(
&
err
,
trx
,
thr
,
NULL
);
if
(
was_lock_wait
)
{
goto
run_again
;
}
trx
->
op_info
=
(
char
*
)
""
;
return
(
err
);
}
que_thr_stop_for_mysql_no_error
(
thr
,
trx
);
trx
->
op_info
=
(
char
*
)
""
;
return
((
int
)
err
);
}
/*************************************************************************
Unlocks a table lock possibly reserved by trx. */
void
row_unlock_table_for_mysql
(
/*=======================*/
trx_t
*
trx
)
/* in: transaction */
{
if
(
!
trx
->
n_tables_locked
)
{
return
;
}
mutex_enter
(
&
kernel_mutex
);
lock_release_tables_off_kernel
(
trx
);
mutex_exit
(
&
kernel_mutex
);
}
/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
row_lock_table_for_mysql
(
/*=====================*/
/* out: error code or DB_SUCCESS */
row_prebuilt_t
*
prebuilt
)
/* in: prebuilt struct in the MySQL
table handle */
{
trx_t
*
trx
=
prebuilt
->
trx
;
que_thr_t
*
thr
;
ulint
err
;
ibool
was_lock_wait
;
ut_ad
(
trx
);
ut_ad
(
trx
->
mysql_thread_id
==
os_thread_get_curr_id
());
trx
->
op_info
=
(
char
*
)
"setting table lock"
;
if
(
prebuilt
->
sel_graph
==
NULL
)
{
/* Build a dummy select query graph */
row_prebuild_sel_graph
(
prebuilt
);
}
/* We use the select query graph as the dummy graph needed
in the lock module call */
thr
=
que_fork_get_first_thr
(
prebuilt
->
sel_graph
);
que_thr_move_to_run_state_for_mysql
(
thr
,
trx
);
run_again:
thr
->
run_node
=
thr
;
thr
->
prev_node
=
thr
->
common
.
parent
;
/* It may be that the current session has not yet started
its transaction, or it has been committed: */
trx_start_if_not_started
(
trx
);
err
=
lock_table
(
0
,
prebuilt
->
table
,
LOCK_AUTO_INC
,
thr
);
err
=
lock_table
(
LOCK_TABLE_EXP
,
prebuilt
->
table
,
prebuilt
->
select_lock_type
,
thr
);
trx
->
error_state
=
err
;
...
...
innobase/trx/trx0trx.c
View file @
8ab135a7
...
...
@@ -151,6 +151,7 @@ trx_create(
trx
->
n_tickets_to_enter_innodb
=
0
;
trx
->
auto_inc_lock
=
NULL
;
trx
->
n_tables_locked
=
0
;
trx
->
read_view_heap
=
mem_heap_create
(
256
);
trx
->
read_view
=
NULL
;
...
...
@@ -278,6 +279,7 @@ trx_free(
ut_a
(
!
trx
->
has_search_latch
);
ut_a
(
!
trx
->
auto_inc_lock
);
ut_a
(
!
trx
->
n_tables_locked
);
ut_a
(
trx
->
dict_operation_lock_mode
==
0
);
...
...
mysql-test/r/innodb-lock.result
0 → 100644
View file @
8ab135a7
drop table if exists t1;
create table t1 (id integer, x integer) engine=INNODB;
insert into t1 values(0, 0);
set autocommit=0;
SELECT * from t1 where id = 0 FOR UPDATE;
id x
0 0
set autocommit=0;
lock table t1 write;
update t1 set x=1 where id = 0;
select * from t1;
id x
0 1
commit;
update t1 set x=2 where id = 0;
commit;
unlock tables;
select * from t1;
id x
0 2
commit;
drop table t1;
mysql-test/r/innodb.result
View file @
8ab135a7
...
...
@@ -431,7 +431,7 @@ Duplicate entry 'test2' for key 2
select * from t1;
id ggid email passwd
1 this will work
3
test2 this will work
4
test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
...
...
mysql-test/t/innodb-lock.test
0 → 100644
View file @
8ab135a7
--
source
include
/
have_innodb
.
inc
connect
(
con1
,
localhost
,
root
,,);
connect
(
con2
,
localhost
,
root
,,);
drop
table
if
exists
t1
;
#
# Testing of explicit table locks
#
connection
con1
;
create
table
t1
(
id
integer
,
x
integer
)
engine
=
INNODB
;
insert
into
t1
values
(
0
,
0
);
set
autocommit
=
0
;
SELECT
*
from
t1
where
id
=
0
FOR
UPDATE
;
connection
con2
;
set
autocommit
=
0
;
# The following statement should hang because con1 is locking the page
--
send
lock
table
t1
write
;
--
sleep
2
;
connection
con1
;
update
t1
set
x
=
1
where
id
=
0
;
select
*
from
t1
;
commit
;
connection
con2
;
reap
;
update
t1
set
x
=
2
where
id
=
0
;
commit
;
unlock
tables
;
connection
con1
;
select
*
from
t1
;
commit
;
drop
table
t1
;
sql/ha_innodb.cc
View file @
8ab135a7
...
...
@@ -4494,12 +4494,11 @@ the SQL statement in case of an error. */
int
ha_innobase
::
external_lock
(
/*=======================*/
/* out: 0
or error code
*/
/* out: 0 */
THD
*
thd
,
/* in: handle to the user thread */
int
lock_type
)
/* in: lock type */
{
row_prebuilt_t
*
prebuilt
=
(
row_prebuilt_t
*
)
innobase_prebuilt
;
int
error
=
0
;
trx_t
*
trx
;
DBUG_ENTER
(
"ha_innobase::external_lock"
);
...
...
@@ -4554,11 +4553,21 @@ ha_innobase::external_lock(
}
if
(
prebuilt
->
select_lock_type
!=
LOCK_NONE
)
{
if
(
thd
->
in_lock_tables
)
{
ulint
error
;
error
=
row_lock_table_for_mysql
(
prebuilt
);
if
(
error
!=
DB_SUCCESS
)
{
error
=
convert_error_code_to_mysql
(
error
,
user_thd
);
DBUG_RETURN
(
error
);
}
}
trx
->
mysql_n_tables_locked
++
;
}
DBUG_RETURN
(
error
);
DBUG_RETURN
(
0
);
}
/* MySQL is releasing a table lock */
...
...
@@ -4566,6 +4575,9 @@ ha_innobase::external_lock(
trx
->
n_mysql_tables_in_use
--
;
prebuilt
->
mysql_has_locked
=
FALSE
;
auto_inc_counter_for_this_stat
=
0
;
if
(
trx
->
n_tables_locked
)
{
row_unlock_table_for_mysql
(
trx
);
}
/* If the MySQL lock count drops to zero we know that the current SQL
statement has ended */
...
...
@@ -4598,7 +4610,7 @@ ha_innobase::external_lock(
}
}
DBUG_RETURN
(
error
);
DBUG_RETURN
(
0
);
}
/****************************************************************************
...
...
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