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
7cb3df01
Commit
7cb3df01
authored
May 24, 2006
by
monty@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge monty@192.168.0.9:/my/mysql-5.0
into mysql.com:/home/my/mysql-5.0
parents
2a2da2f0
9e9ca8b6
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
142 additions
and
14 deletions
+142
-14
mysql-test/r/flush.result
mysql-test/r/flush.result
+7
-0
mysql-test/r/lock_multi.result
mysql-test/r/lock_multi.result
+16
-0
mysql-test/t/flush.test
mysql-test/t/flush.test
+40
-0
mysql-test/t/lock_multi.test
mysql-test/t/lock_multi.test
+32
-0
sql/lock.cc
sql/lock.cc
+25
-9
sql/mysql_priv.h
sql/mysql_priv.h
+1
-0
sql/mysqld.cc
sql/mysqld.cc
+4
-4
sql/sql_base.cc
sql/sql_base.cc
+17
-1
No files found.
mysql-test/r/flush.result
View file @
7cb3df01
...
...
@@ -48,3 +48,10 @@ lock table t1 read, t2 read, t3 read;
flush tables with read lock;
unlock tables;
drop table t1, t2, t3;
create table t1 (c1 int);
create table t2 (c1 int);
lock table t1 write;
flush tables with read lock;
insert into t2 values(1);
unlock tables;
drop table t1, t2;
mysql-test/r/lock_multi.result
View file @
7cb3df01
...
...
@@ -43,3 +43,19 @@ Field Type Null Key Default Extra
a int(11) YES NULL
unlock tables;
drop table t1;
use mysql;
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
FLUSH TABLES;
use mysql;
SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
OPTIMIZE TABLES columns_priv, db, host, user;
Table Op Msg_type Msg_text
mysql.columns_priv optimize status OK
mysql.db optimize status OK
mysql.host optimize status OK
mysql.user optimize status OK
UNLOCK TABLES;
Select_priv
N
use test;
use test;
mysql-test/t/flush.test
View file @
7cb3df01
...
...
@@ -102,3 +102,43 @@ unlock tables;
drop
table
t1
,
t2
,
t3
;
# End of 4.1 tests
#
# Test of deadlock problem when doing FLUSH TABLE with read lock
# (Bug was in NTPL threads in Linux when using different mutex while
# waiting for a condtion variable)
create
table
t1
(
c1
int
);
create
table
t2
(
c1
int
);
connect
(
con1
,
localhost
,
root
,,);
connect
(
con3
,
localhost
,
root
,,);
connection
con1
;
lock
table
t1
write
;
connection
con2
;
send
flush
tables
with
read
lock
;
--
sleep
1
connection
con3
;
send
insert
into
t2
values
(
1
);
--
sleep
1
connection
con1
;
unlock
tables
;
disconnect
con1
;
connection
con2
;
reap
;
disconnect
con2
;
connection
con3
;
# It hangs here (insert into t2 does not end).
reap
;
disconnect
con3
;
connection
default
;
drop
table
t1
,
t2
;
# End of 5.0 tests
mysql-test/t/lock_multi.test
View file @
7cb3df01
...
...
@@ -107,3 +107,35 @@ show columns from t1;
connection
locker
;
unlock
tables
;
drop
table
t1
;
#
# Bug#16986 - Deadlock condition with MyISAM tables
#
connection
locker
;
use
mysql
;
LOCK
TABLES
columns_priv
WRITE
,
db
WRITE
,
host
WRITE
,
user
WRITE
;
FLUSH
TABLES
;
--
sleep
1
#
connection
reader
;
use
mysql
;
#NOTE: This must be a multi-table select, otherwise the deadlock will not occur
send
SELECT
user
.
Select_priv
FROM
user
,
db
WHERE
user
.
user
=
db
.
user
LIMIT
1
;
--
sleep
1
#
connection
locker
;
# Make test case independent from earlier grants.
--
replace_result
"Table is already up to date"
"OK"
OPTIMIZE
TABLES
columns_priv
,
db
,
host
,
user
;
UNLOCK
TABLES
;
#
connection
reader
;
reap
;
use
test
;
#
connection
locker
;
use
test
;
#
connection
default
;
# End of 5.0 tests
sql/lock.cc
View file @
7cb3df01
...
...
@@ -1138,8 +1138,9 @@ bool lock_global_read_lock(THD *thd)
if
(
!
thd
->
global_read_lock
)
{
const
char
*
old_message
;
(
void
)
pthread_mutex_lock
(
&
LOCK_global_read_lock
);
const
char
*
old_message
=
thd
->
enter_cond
(
&
COND_refresh
,
&
LOCK_global_read_lock
,
old_message
=
thd
->
enter_cond
(
&
COND_global_read_lock
,
&
LOCK_global_read_lock
,
"Waiting to get readlock"
);
DBUG_PRINT
(
"info"
,
(
"waiting_for: %d protect_against: %d"
,
...
...
@@ -1147,7 +1148,7 @@ bool lock_global_read_lock(THD *thd)
waiting_for_read_lock
++
;
while
(
protect_against_global_read_lock
&&
!
thd
->
killed
)
pthread_cond_wait
(
&
COND_
refresh
,
&
LOCK_global_read_lock
);
pthread_cond_wait
(
&
COND_
global_read_lock
,
&
LOCK_global_read_lock
);
waiting_for_read_lock
--
;
if
(
thd
->
killed
)
{
...
...
@@ -1169,9 +1170,15 @@ bool lock_global_read_lock(THD *thd)
DBUG_RETURN
(
0
);
}
void
unlock_global_read_lock
(
THD
*
thd
)
{
uint
tmp
;
DBUG_ENTER
(
"unlock_global_read_lock"
);
DBUG_PRINT
(
"info"
,
(
"global_read_lock: %u global_read_lock_blocks_commit: %u"
,
global_read_lock
,
global_read_lock_blocks_commit
));
pthread_mutex_lock
(
&
LOCK_global_read_lock
);
tmp
=
--
global_read_lock
;
if
(
thd
->
global_read_lock
==
MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT
)
...
...
@@ -1179,8 +1186,13 @@ void unlock_global_read_lock(THD *thd)
pthread_mutex_unlock
(
&
LOCK_global_read_lock
);
/* Send the signal outside the mutex to avoid a context switch */
if
(
!
tmp
)
pthread_cond_broadcast
(
&
COND_refresh
);
{
DBUG_PRINT
(
"signal"
,
(
"Broadcasting COND_global_read_lock"
));
pthread_cond_broadcast
(
&
COND_global_read_lock
);
}
thd
->
global_read_lock
=
0
;
DBUG_VOID_RETURN
;
}
#define must_wait (global_read_lock && \
...
...
@@ -1218,11 +1230,15 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
*/
DBUG_RETURN
(
is_not_commit
);
}
old_message
=
thd
->
enter_cond
(
&
COND_
refresh
,
&
LOCK_global_read_lock
,
old_message
=
thd
->
enter_cond
(
&
COND_
global_read_lock
,
&
LOCK_global_read_lock
,
"Waiting for release of readlock"
);
while
(
must_wait
&&
!
thd
->
killed
&&
(
!
abort_on_refresh
||
thd
->
version
==
refresh_version
))
(
void
)
pthread_cond_wait
(
&
COND_refresh
,
&
LOCK_global_read_lock
);
{
DBUG_PRINT
(
"signal"
,
(
"Waiting for COND_global_read_lock"
));
(
void
)
pthread_cond_wait
(
&
COND_global_read_lock
,
&
LOCK_global_read_lock
);
DBUG_PRINT
(
"signal"
,
(
"Got COND_global_read_lock"
));
}
if
(
thd
->
killed
)
result
=
1
;
}
...
...
@@ -1251,7 +1267,7 @@ void start_waiting_global_read_lock(THD *thd)
(
waiting_for_read_lock
||
global_read_lock_blocks_commit
));
(
void
)
pthread_mutex_unlock
(
&
LOCK_global_read_lock
);
if
(
tmp
)
pthread_cond_broadcast
(
&
COND_
refresh
);
pthread_cond_broadcast
(
&
COND_
global_read_lock
);
DBUG_VOID_RETURN
;
}
...
...
@@ -1273,10 +1289,10 @@ bool make_global_read_lock_block_commit(THD *thd)
/* For testing we set up some blocking, to see if we can be killed */
DBUG_EXECUTE_IF
(
"make_global_read_lock_block_commit_loop"
,
protect_against_global_read_lock
++
;);
old_message
=
thd
->
enter_cond
(
&
COND_
refresh
,
&
LOCK_global_read_lock
,
old_message
=
thd
->
enter_cond
(
&
COND_
global_read_lock
,
&
LOCK_global_read_lock
,
"Waiting for all running commits to finish"
);
while
(
protect_against_global_read_lock
&&
!
thd
->
killed
)
pthread_cond_wait
(
&
COND_
refresh
,
&
LOCK_global_read_lock
);
pthread_cond_wait
(
&
COND_
global_read_lock
,
&
LOCK_global_read_lock
);
DBUG_EXECUTE_IF
(
"make_global_read_lock_block_commit_loop"
,
protect_against_global_read_lock
--
;);
if
((
error
=
test
(
thd
->
killed
)))
...
...
sql/mysql_priv.h
View file @
7cb3df01
...
...
@@ -1220,6 +1220,7 @@ extern pthread_mutex_t LOCK_des_key_file;
#endif
extern
rw_lock_t
LOCK_grant
,
LOCK_sys_init_connect
,
LOCK_sys_init_slave
;
extern
pthread_cond_t
COND_refresh
,
COND_thread_count
,
COND_manager
;
extern
pthread_cond_t
COND_global_read_lock
;
extern
pthread_attr_t
connection_attrib
;
extern
I_List
<
THD
>
threads
;
extern
I_List
<
NAMED_LIST
>
key_caches
;
...
...
sql/mysqld.cc
View file @
7cb3df01
...
...
@@ -516,7 +516,7 @@ pthread_mutex_t LOCK_prepared_stmt_count;
pthread_mutex_t
LOCK_des_key_file
;
#endif
rw_lock_t
LOCK_grant
,
LOCK_sys_init_connect
,
LOCK_sys_init_slave
;
pthread_cond_t
COND_refresh
,
COND_thread_count
;
pthread_cond_t
COND_refresh
,
COND_thread_count
,
COND_global_read_lock
;
pthread_t
signal_thread
;
pthread_attr_t
connection_attrib
;
...
...
@@ -1248,6 +1248,7 @@ static void clean_up_mutexes()
(
void
)
pthread_mutex_destroy
(
&
LOCK_prepared_stmt_count
);
(
void
)
pthread_cond_destroy
(
&
COND_thread_count
);
(
void
)
pthread_cond_destroy
(
&
COND_refresh
);
(
void
)
pthread_cond_destroy
(
&
COND_global_read_lock
);
(
void
)
pthread_cond_destroy
(
&
COND_thread_cache
);
(
void
)
pthread_cond_destroy
(
&
COND_flush_thread_cache
);
(
void
)
pthread_cond_destroy
(
&
COND_manager
);
...
...
@@ -1670,13 +1671,11 @@ void end_thread(THD *thd, bool put_in_cache)
}
}
DBUG_PRINT
(
"info"
,
(
"sending a broadcast"
))
/* Tell main we are ready */
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
/* It's safe to broadcast outside a lock (COND... is not deleted here) */
DBUG_PRINT
(
"signal"
,
(
"Broadcasting COND_thread_count"
));
(
void
)
pthread_cond_broadcast
(
&
COND_thread_count
);
DBUG_PRINT
(
"info"
,
(
"unlocked thread_count mutex"
))
#ifdef ONE_THREAD
if
(
!
(
test_flags
&
TEST_NO_THREADS
))
// For debugging under Linux
#endif
...
...
@@ -2824,6 +2823,7 @@ static int init_thread_environment()
(
void
)
my_rwlock_init
(
&
LOCK_grant
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_thread_count
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_refresh
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_global_read_lock
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_thread_cache
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_flush_thread_cache
,
NULL
);
(
void
)
pthread_cond_init
(
&
COND_manager
,
NULL
);
...
...
sql/sql_base.cc
View file @
7cb3df01
...
...
@@ -316,7 +316,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
bool
found
=
1
;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT
(
"info"
,
(
"Waiting for other
s
threads to close their open tables"
));
(
"Waiting for other threads to close their open tables"
));
while
(
found
&&
!
thd
->
killed
)
{
found
=
0
;
...
...
@@ -326,6 +326,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
if
((
table
->
s
->
version
)
<
refresh_version
&&
table
->
db_stat
)
{
found
=
1
;
DBUG_PRINT
(
"signal"
,
(
"Waiting for COND_refresh"
));
pthread_cond_wait
(
&
COND_refresh
,
&
LOCK_open
);
break
;
}
...
...
@@ -1046,6 +1047,7 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
void
wait_for_refresh
(
THD
*
thd
)
{
DBUG_ENTER
(
"wait_for_refresh"
);
safe_mutex_assert_owner
(
&
LOCK_open
);
/* Wait until the current table is up to date */
...
...
@@ -1063,6 +1065,7 @@ void wait_for_refresh(THD *thd)
thd
->
mysys_var
->
current_cond
=
0
;
thd
->
proc_info
=
proc_info
;
pthread_mutex_unlock
(
&
thd
->
mysys_var
->
mutex
);
DBUG_VOID_RETURN
;
}
...
...
@@ -1346,6 +1349,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{
if
(
table
->
s
->
version
!=
refresh_version
)
{
DBUG_PRINT
(
"note"
,
(
"Found table '%s.%s' with different refresh version"
,
table_list
->
db
,
table_list
->
table_name
));
if
(
flags
&
MYSQL_LOCK_IGNORE_FLUSH
)
{
/* Force close at once after usage */
...
...
@@ -5123,6 +5129,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
TABLE
*
table
;
bool
result
=
0
,
signalled
=
0
;
DBUG_ENTER
(
"remove_table_from_cache"
);
DBUG_PRINT
(
"enter"
,
(
"Table: '%s.%s' flags: %u"
,
db
,
table_name
,
flags
));
key_length
=
(
uint
)
(
strmov
(
strmov
(
key
,
db
)
+
1
,
table_name
)
-
key
)
+
1
;
for
(;;)
...
...
@@ -5147,7 +5154,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
{
in_use
->
some_tables_deleted
=
1
;
if
(
table
->
db_stat
)
{
DBUG_PRINT
(
"info"
,
(
"Found another active instance of the table"
));
result
=
1
;
}
/* Kill delayed insert threads */
if
((
in_use
->
system_thread
&
SYSTEM_THREAD_DELAYED_INSERT
)
&&
!
in_use
->
killed
)
...
...
@@ -5182,6 +5192,12 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
VOID
(
hash_delete
(
&
open_cache
,(
byte
*
)
unused_tables
));
if
(
result
&&
(
flags
&
RTFC_WAIT_OTHER_THREAD_FLAG
))
{
/*
Signal any thread waiting for tables to be freed to
reopen their tables
*/
(
void
)
pthread_cond_broadcast
(
&
COND_refresh
);
DBUG_PRINT
(
"info"
,
(
"Waiting for refresh signal"
));
if
(
!
(
flags
&
RTFC_CHECK_KILLED_FLAG
)
||
!
thd
->
killed
)
{
dropping_tables
++
;
...
...
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