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
7d98fb7e
Commit
7d98fb7e
authored
Feb 28, 2007
by
kostja@bodhi.local
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add more comments to open_table and open_tables. No real changes.
parent
03fa3e5a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
111 additions
and
5 deletions
+111
-5
sql/sql_base.cc
sql/sql_base.cc
+111
-5
No files found.
sql/sql_base.cc
View file @
7d98fb7e
...
...
@@ -1210,6 +1210,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
int4store
(
key
+
key_length
,
thd
->
server_id
);
int4store
(
key
+
key_length
+
4
,
thd
->
variables
.
pseudo_thread_id
);
/*
Unless requested otherwise, try to resolve this table in the list
of temporary tables of this thread. In MySQL temporary tables
are always thread-local and "shadow" possible base tables with the
same name. This block implements the behaviour.
TODO: move this block into a separate function.
*/
if
(
!
table_list
->
skip_temporary
)
{
for
(
table
=
thd
->
temporary_tables
;
table
;
table
=
table
->
next
)
...
...
@@ -1218,6 +1225,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
!
memcmp
(
table
->
s
->
table_cache_key
,
key
,
key_length
+
TMP_TABLE_KEY_EXTRA
))
{
/*
We're trying to use the same temporary table twice in a query.
Right now we don't support this because a temporary table
is always represented by only one TABLE object in THD, and
it can not be cloned. Emit an error for an unsupported behaviour.
*/
if
(
table
->
query_id
==
thd
->
query_id
||
thd
->
prelocked_mode
&&
table
->
query_id
)
{
...
...
@@ -1233,6 +1246,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
}
/*
The table is not temporary - if we're in pre-locked or LOCK TABLES
mode, let's try to find the requested table in the list of pre-opened
and locked tables. If the table is not there, return an error - we can't
open not pre-opened tables in pre-locked/LOCK TABLES mode.
TODO: move this block into a separate function.
*/
if
(
!
(
flags
&
MYSQL_OPEN_IGNORE_LOCKED_TABLES
)
&&
(
thd
->
locked_tables
||
thd
->
prelocked_mode
))
{
// Using table locks
...
...
@@ -1304,7 +1324,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
goto
reset
;
}
/*
is it view
?
Is this table a view and not a base table
?
(it is work around to allow to open view with locked tables,
real fix will be made after definition cache will be made)
*/
...
...
@@ -1338,8 +1358,32 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
DBUG_RETURN
(
0
);
}
/*
Non pre-locked/LOCK TABLES mode, and the table is not temporary:
this is the normal use case.
Now we should:
- try to find the table in the table cache.
- if one of the discovered TABLE instances is name-locked
(table->s->version == 0) or some thread has started FLUSH TABLES
(refresh_version > table->s->version), back off -- we have to wait
until no one holds a name lock on the table.
- if there is no such TABLE in the name cache, read the table definition
and insert it into the cache.
We perform all of the above under LOCK_open which currently protects
the open cache (also known as table cache) and table definitions stored
on disk.
*/
VOID
(
pthread_mutex_lock
(
&
LOCK_open
));
/*
If it's the first table from a list of tables used in a query,
remember refresh_version (the version of open_cache state).
If the version changes while we're opening the remaining tables,
we will have to back off, close all the tables opened-so-far,
and try to reopen them.
Note: refresh_version is currently changed only during FLUSH TABLES.
*/
if
(
!
thd
->
open_tables
)
thd
->
version
=
refresh_version
;
else
if
((
thd
->
version
!=
refresh_version
)
&&
...
...
@@ -1356,12 +1400,39 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if
(
thd
->
handler_tables
)
mysql_ha_flush
(
thd
,
(
TABLE_LIST
*
)
NULL
,
MYSQL_HA_REOPEN_ON_USAGE
,
TRUE
);
/*
Actually try to find the table in the open_cache.
The cache may contain several "TABLE" instances for the same
physical table. The instances that are currently "in use" by
some thread have their "in_use" member != NULL.
There is no good reason for having more than one entry in the
hash for the same physical table, except that we use this as
an implicit "pending locks queue" - see
wait_for_locked_table_names for details.
*/
for
(
table
=
(
TABLE
*
)
hash_first
(
&
open_cache
,
(
byte
*
)
key
,
key_length
,
&
state
);
table
&&
table
->
in_use
;
table
=
(
TABLE
*
)
hash_next
(
&
open_cache
,
(
byte
*
)
key
,
key_length
,
&
state
))
{
/*
Normally, table->s->version contains the value of
refresh_version from the moment when this table was
(re-)opened and added to the cache.
If since then we did (or just started) FLUSH TABLES
statement, refresh_version has been increased.
For "name-locked" TABLE instances, table->s->version is set
to 0 (see lock_table_name for details).
In case there is a pending FLUSH TABLES or a name lock, we
need to back off and re-start opening tables.
If we do not back off now, we may dead lock in case of lock
order mismatch with some other thread:
c1: name lock t1; -- sort of exclusive lock
c2: open t2; -- sort of shared lock
c1: name lock t2; -- blocks
c2: open t1; -- blocks
*/
if
(
table
->
s
->
version
!=
refresh_version
)
{
DBUG_PRINT
(
"note"
,
...
...
@@ -1375,16 +1446,35 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
/*
There is a refresh in progress for this table
Wait until the table is freed or the thread is killed.
Back off, part 1: mark the table as "unused" for the
purpose of name-locking by setting table->db_stat to 0. Do
that only for the tables in this thread that have an old
table->s->version (this is an optimization (?)).
table->db_stat == 0 signals wait_for_locked_table_names
that the tables in question are not used any more. See
table_is_used call for details.
*/
close_old_data_files
(
thd
,
thd
->
open_tables
,
0
,
0
);
/*
Back-off part 2: try to avoid "busy waiting" on the table:
if the table is in use by some other thread, we suspend
and wait till the operation is complete: when any
operation that juggles with table->s->version completes,
it broadcasts COND_refresh condition variable.
*/
if
(
table
->
in_use
!=
thd
)
{
wait_for_refresh
(
thd
);
/* wait_for_refresh will unlock LOCK_open for us */
}
else
{
VOID
(
pthread_mutex_unlock
(
&
LOCK_open
));
}
/*
There is a refresh in progress for this table.
Signal the caller that it has to try again.
*/
if
(
refresh
)
*
refresh
=
1
;
DBUG_RETURN
(
0
);
...
...
@@ -1392,6 +1482,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
if
(
table
)
{
/* Unlink the table from "unused_tables" list. */
if
(
table
==
unused_tables
)
{
// First unused
unused_tables
=
unused_tables
->
next
;
// Remove from link
...
...
@@ -1404,6 +1495,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
else
{
/* Insert a new TABLE instance into the open cache */
TABLE_SHARE
*
share
;
int
error
;
/* Free cache if too big */
...
...
@@ -2145,6 +2237,10 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
}
}
/*
For every table in the list of tables to open, try to find or open
a table.
*/
for
(
tables
=
*
start
;
tables
;
tables
=
tables
->
next_global
)
{
/*
...
...
@@ -2159,6 +2255,12 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
goto
process_view_routines
;
continue
;
}
/*
If this TABLE_LIST object is a placeholder for an information_schema
table, create a temporary table to represent the information_schema
table in the query. Do not fill it yet - will be filled during
execution.
*/
if
(
tables
->
schema_table
)
{
if
(
!
mysql_schema_table
(
thd
,
thd
->
lex
,
tables
))
...
...
@@ -2166,7 +2268,11 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
DBUG_RETURN
(
-
1
);
}
(
*
counter
)
++
;
/*
Not a placeholder: must be a base table or a view, and the table is
not opened yet. Try to open the table.
*/
if
(
!
tables
->
table
&&
!
(
tables
->
table
=
open_table
(
thd
,
tables
,
&
new_frm_mem
,
&
refresh
,
flags
)))
{
...
...
@@ -2273,7 +2379,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
{
/*
Serious error during reading stored routines from mysql.proc table.
Something
'
s wrong with the table or its contents, and an error has
Something
i
s wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result
=
-
1
;
...
...
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