Below is the list of changes that have just been committed into a local
5.1 repository of marcsql. When marcsql does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-06-28 16:13:43-06:00, malff@weblab.(none) +32 -0
Bug#25422 (Hang with log tables)
Bug 29129 (Resetting general_log while the GLOBAL READ LOCK is set causes
a deadlock)
NOTE TO REVIEWER:
There is still an opened issue with this patch, see mysql-tests/t/disabled.def
The test rpl_optimize dead locks, but it's unclear if this is because:
- a new bug was introduced by this patch
- an existing unrelated bug was exposed by this patch
To discuss during review, this point needs further investigation.
------
Prior to this fix, the server would hang when performing concurrent
ALTER TABLE or TRUNCATE TABLE statements against the LOG TABLES,
which are mysql.general_log and mysql.slow_log.
The root cause traces to the following code:
in sql_base.cc, open_table()
if (table->in_use != thd)
{
/* wait_for_condition will unlock LOCK_open for us */
wait_for_condition(thd, &LOCK_open, &COND_refresh);
}
The problem with this code is that the current implementation of the
LOGGER creates 'fake' THD objects, like
- Log_to_csv_event_handler::general_log_thd
- Log_to_csv_event_handler::slow_log_thd
which are not associated to a real thread running in the server,
so that waiting for these non-existing threads to release table locks
cause the dead lock.
In general, the design of Log_to_csv_event_handler does not fit into the
general architecture of the server, so that the concept of general_log_thd
and slow_log_thd has to be abandoned:
- this implementation does not work with table locking
- it will not work with commands like SHOW PROCESSLIST
- having the log tables always opened does not integrate well with DDL
operations / FLUSH TABLES / SET GLOBAL READ_ONLY
With this patch, the fundamental design of the LOGGER has been changed to:
- always open and close a log table when writing a log
- remove totally the usage of fake THD objects
- clarify how locking of log tables is implemented in general.
Changing the locking design for log tables had some impact in several areas.
The total change consist of:
Part I: Technical changes
1)
bool TABLE_SHARE::system was too close to bool TABLE_SHARE::system_table,
and has been renamed bool TABLE_SHARE::one_record_table
2)
bool TABLE_SHARE::system_table and bool TABLE_SHARE::log_table are related.
Instead of multiplying various "is_X" "is_Y" boolean flags, the attribute
TABLE_CATEGORY TABLE_SHARE::table_category has been introduced, that better
describe the nature of the table.
3)
The enum TABLE_CATEGORY has been introduced, see the comments there.
Special exceptions regarding FLUSH TABLES WITH READ LOCK or
SET GLOBAL READ_ONLY=ON, in lock.cc, are now implemented with more clarity
with the use of honor_global_locks().
In general, helpers like honor_XYZ() are encouraged, as this breaks the
correlation between
- how a table behaves with regards to 1 property (global read lock, ...)
- what the table is used for (user, system, ...)
4)
my_bool TABLE_SHARE::locked_by_logger has been removed, this was an artificial
hack.
5)
The previous implementation confused:
- 'system table' with ENGINE = MYISAM
- 'log table' with ENGINE = CSV
so that logic related to enforcing constraints for what the SQL layer
considers 'system' or 'log' tables was not implemented in the SQL layer but
in the storage engines.
The methods:
- handler::check_if_locking_is_allowed
- handler::check_if_log_table_locking_is_allowed
- ha_tina::check_if_locking_is_allowed
- ha_myisam::check_if_locking_is_allowed
have been removed, and the logic implemented in lock.cc instead.
6)
The fake threads, Log_to_csv_event_handler::general_log_thd and
Log_to_csv_event_handler::slow_log_thd, are removed
7)
In general, a lot of code in log.h / log.cc dealing with opening / closing
tables has been removed.
8)
Writing to the log tables is still a privileged operation.
Before, it was enforced by testing that the 'current thread is the logger
thread'. Now, it's enforced by the use of the internal flag
OPTION_INTERNAL_PRIVILEGE
9)
TRUNCATE TABLE does not interfere with the logger implementation any more,
all the code used to 'shutdown the logger, truncate, then restart the logger'
is removed, and the operation is online.
TRUNCATE TABLE uses OPTION_INTERNAL_PRIVILEGE, since it may need to use
write locks.
10)
RENAME TABLE does not interfere with the logger implementation any more,
regular table locking rules should apply even with log tables.
11)
Special rules for log tables in ALTER TABLES have been implemented in a
dedicated helper/wrapper, for clarity.
mysql_alter_table() uses OPTION_INTERNAL_PRIVILEGE, then invokes the
ALTER TABLE implementation: mysql_alter_table_impl()
This ensures that -- given the complexity of mysql_alter_table_impl() --
every path of execution properly unset OPTION_INTERNAL_PRIVILEGE at the end.
Note that the operation is online, as the logger is not locked.
Part II: functional changes
12)
The previous implementation enforced that :
- LOCK TABLE mysql.general_log WRITE
- LOCK TABLE mysql.general_log READ
was prohibited (even for SUPER), while
- LOCK TABLE mysql.general_log READ LOCAL
was allowed.
The rational behind this was that WRITE and READ would freeze the server
when running with SET GLOBAL GENERAL_LOG=ON, and should (rightfully) be
prohibited.
Allowing READ LOCAL was assuming that no dead locks can occur because of this
lock, so that it's not harmful.
However, with the following scenario:
THD1: LOCK TABLE mysql.general_log READ LOCAL;
THD2: TRUNCATE TABLE mysql.general_log;
THD1: <any query, even "select 1 from dual> --> deadlock.
The dead lock occurs because TRUNCATE uses a name lock and waits for *all*
locks to disappear.
THD1 dead locks while writing to the general_log, which can't get a write lock
because of TRUNCATE.
So, allowing even READ LOCAL on log tables can lead to a complete dead lock of
the server, where 'complete' means :
- new clients can't connect (stuck while printing in the general log)
- new queries from existing clients can't execute (same)
- the server does not respond to kill -15 (as seen during testing)
The functional change introduced by this patch is to deny *any* form of
locking what-so-ever on log tables, so that :
LOCK TABLE mysql.general_log READ LOCAL is now denied.
13)
FLUSH LOGS does not flush the log tables any more.
14)
FLUSH TABLES does flush the log tables, it used to ignore them.
Part III: more technical changes
15)
Implementing the restriction 12) above exposed a bug in mysqldump, which would
ignore some tables in dump_all_tables_in_db(), but forget to ignore the same
in dump_all_views_in_db().
This has been fixed.
16)
mysqldump would also issue an empty "LOCK TABLE" command when all the tables
to lock are to be ignored (numrows == 0), instead of not issuing the query.
This has been fixed.
17)
Internal errors handlers could intercept errors but not warnings
(see sql_error.cc), this has been fixed.
It was found because writing to the general log or the slow log needs to
filter out any error or warning, to avoid affecting the client performing
the query with unrelated noise.
client/mysqldump.c@stripped, 2007-06-28 16:13:38-06:00, malff@weblab.(none) +15 -4
Don't lock tables in the ignore list.
Don't issue empty LOCK TABLES queries.
mysql-test/r/log_state.result@stripped, 2007-06-28 16:13:38-06:00, malff@weblab.(none) +22 -0
Adjust test results
mysql-test/r/log_tables.result@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +98
-24
Adjust test results
mysql-test/r/ps.result@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +23 -31
Adjust test results
mysql-test/r/show_check.result@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +14
-17
Adjust test results
mysql-test/r/status.result@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +6 -6
Adjust test results
mysql-test/t/disabled.def@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +4 -0
Disabled rpl_optimize
mysql-test/t/log_state.test@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +53 -0
Added tests for Bug#29129
mysql-test/t/log_tables.test@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +157
-63
Can not lock a log table: adjusted the tests.
Added tests for Bug#25422
mysql-test/t/ps.test@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +7 -0
Make the test output deterministic
mysql-test/t/show_check.test@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +7 -0
Make the test output deterministic
sql/handler.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +7 -28
Moved logic for system / log tables in the SQL layer.
sql/handler.h@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +1 -38
Moved logic for system / log tables in the SQL layer.
sql/lock.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +80 -15
Revised locking of log tables
sql/log.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +246 -420
Major cleanup: changed how log tables are locked / written to
sql/log.h@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +7 -75
Major cleanup: changed how log tables are locked / written to.
sql/mysql_priv.h@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +16 -1
performance schema helpers
sql/set_var.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +5 -11
log tables cleanup
sql/share/errmsg.txt@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +1 -1
Changed the wording of ER_CANT_READ_LOCK_LOG_TABLE
sql/sql_base.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +104 -38
log tables cleanup
performance schema helpers
sql/sql_delete.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +28 -24
log tables cleanup in TRUNCATE
sql/sql_error.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +3 -0
Internal handlers can also intercept warnings
sql/sql_rename.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +0 -20
log tables cleanup in RENAME
sql/sql_select.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +1 -1
TABLE_SHARE::system -> TABLE_SHARE::one_record_table
sql/sql_show.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +0 -3
Move INFORMATION_SCHEMA_NAME to table.cc
sql/sql_table.cc@stripped, 2007-06-28 16:13:39-06:00, malff@weblab.(none) +77 -55
log tables cleanup (admin operations, ALTER TABLE)
sql/table.cc@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +62 -20
Implemented TABLE_CATEGORY.
sql/table.h@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +111 -14
Implemented TABLE_CATEGORY.
storage/csv/ha_tina.cc@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +0 -12
Moved logic for system / log tables in the SQL layer.
storage/csv/ha_tina.h@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +0 -5
Moved logic for system / log tables in the SQL layer.
storage/myisam/ha_myisam.cc@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +1 -35
Moved logic for system / log tables in the SQL layer.
storage/myisam/ha_myisam.h@stripped, 2007-06-28 16:13:40-06:00, malff@weblab.(none) +0 -5
Moved logic for system / log tables in the SQL layer.
diff -Nrup a/client/mysqldump.c b/client/mysqldump.c
--- a/client/mysqldump.c 2007-06-05 15:23:54 -06:00
+++ b/client/mysqldump.c 2007-06-28 16:13:38 -06:00
@@ -3372,11 +3372,12 @@ static int dump_all_tables_in_db(char *d
{
DYNAMIC_STRING query;
init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
- for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
+ for (numrows= 0 ; (table= getTableName(1)) ; )
{
char *end= strmov(afterdot, table);
if (include_table(hash_key,end - hash_key))
{
+ numrows++;
dynstr_append_checked(&query, quote_name(table, table_buff, 1));
dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
}
@@ -3450,6 +3451,11 @@ static my_bool dump_all_views_in_db(char
char *table;
uint numrows;
char table_buff[NAME_LEN*2+3];
+ char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
+ char *afterdot;
+
+ afterdot= strmov(hash_key, database);
+ *afterdot++= '.';
if (init_dumping(database, init_dumping_views))
return 1;
@@ -3459,10 +3465,15 @@ static my_bool dump_all_views_in_db(char
{
DYNAMIC_STRING query;
init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
- for (numrows= 0 ; (table= getTableName(1)); numrows++)
+ for (numrows= 0 ; (table= getTableName(1)); )
{
- dynstr_append_checked(&query, quote_name(table, table_buff, 1));
- dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
+ char *end= strmov(afterdot, table);
+ if (include_table(hash_key,end - hash_key))
+ {
+ numrows++;
+ dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+ dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
+ }
}
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
DB_error(mysql, "when using LOCK TABLES");
diff -Nrup a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result
--- a/mysql-test/r/log_state.result 2007-02-20 13:00:04 -07:00
+++ b/mysql-test/r/log_state.result 2007-06-28 16:13:38 -06:00
@@ -153,3 +153,25 @@ select * from mysql.general_log;
event_time user_host thread_id server_id command_type argument
TIMESTAMP USER_HOST # 1 Query drop table t1
TIMESTAMP USER_HOST # 1 Query select * from mysql.general_log
+SET @old_general_log_state = @@global.general_log;
+set @old_slow_log_state = @@global.slow_query_log;
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+FLUSH TABLES WITH READ LOCK;
+SET GLOBAL general_log = OFF;
+SET GLOBAL slow_query_log = OFF;
+UNLOCK TABLES;
+FLUSH TABLES WITH READ LOCK;
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+UNLOCK TABLES;
+SET GLOBAL READ_ONLY = ON;
+SET GLOBAL general_log = OFF;
+SET GLOBAL slow_query_log = OFF;
+SET GLOBAL READ_ONLY = OFF;
+SET GLOBAL READ_ONLY = ON;
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+SET GLOBAL READ_ONLY = OFF;
+SET GLOBAL general_log = @old_general_log_state;
+SET GLOBAL slow_query_log = @old_slow_log_state;
diff -Nrup a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result
--- a/mysql-test/r/log_tables.result 2007-06-13 17:34:41 -06:00
+++ b/mysql-test/r/log_tables.result 2007-06-28 16:13:39 -06:00
@@ -33,26 +33,33 @@ ERROR HY000: You can't write-lock a log
lock tables mysql.slow_log WRITE;
ERROR HY000: You can't write-lock a log table. Only read access is possible
lock tables mysql.general_log READ;
-ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead
+ERROR HY000: You can't use locks with log tables.
lock tables mysql.slow_log READ;
-ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead
+ERROR HY000: You can't use locks with log tables.
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
-unlock tables;
-lock tables mysql.general_log READ LOCAL;
+ERROR HY000: You can't use locks with log tables.
flush logs;
-unlock tables;
-select "Mark that we woke up from flush logs in the test"
- as "test passed";
-test passed
-Mark that we woke up from flush logs in the test
-lock tables mysql.general_log READ LOCAL;
-truncate mysql.general_log;
-unlock tables;
-select "Mark that we woke up from TRUNCATE in the test"
- as "test passed";
-test passed
-Mark that we woke up from TRUNCATE in the test
-use test;
+flush tables;
+SET GLOBAL GENERAL_LOG=ON;
+SET GLOBAL SLOW_QUERY_LOG=ON;
+show open tables;
+Database Table In_use Name_locked
+mysql general_log 0 0
+flush logs;
+show open tables;
+Database Table In_use Name_locked
+mysql general_log 0 0
+flush tables;
+show open tables;
+Database Table In_use Name_locked
+mysql general_log 0 0
+SET GLOBAL GENERAL_LOG=OFF;
+SET GLOBAL SLOW_QUERY_LOG=OFF;
+flush tables;
+show open tables;
+Database Table In_use Name_locked
+SET GLOBAL GENERAL_LOG=ON;
+SET GLOBAL SLOW_QUERY_LOG=ON;
truncate table mysql.general_log;
set names utf8;
create table bug16905 (s char(15) character set utf8 default 'пусто');
@@ -71,7 +78,7 @@ sleep(2)
0
select * from mysql.slow_log;
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
-TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2)
+TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 mysql 0 0 1 select sleep(2)
alter table mysql.general_log engine=myisam;
ERROR HY000: You cannot 'ALTER' a log table if logging is enabled
alter table mysql.slow_log engine=myisam;
@@ -162,11 +169,9 @@ ERROR HY000: You can't write-lock a log
lock tables mysql.slow_log WRITE;
ERROR HY000: You can't write-lock a log table. Only read access is possible
lock tables mysql.general_log READ;
-ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead
+ERROR HY000: You can't use locks with log tables.
lock tables mysql.slow_log READ;
-ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead
-lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
-unlock tables;
+ERROR HY000: You can't use locks with log tables.
set global general_log='OFF';
set global slow_query_log='OFF';
set @save_storage_engine= @@session.storage_engine;
@@ -217,6 +222,7 @@ flush tables with read lock;
unlock tables;
use mysql;
lock tables general_log read local, help_category read local;
+ERROR HY000: You can't use locks with log tables.
unlock tables;
use mysql;
RENAME TABLE general_log TO renamed_general_log;
@@ -258,9 +264,9 @@ RENAME TABLE general_log TO general_log2
set global slow_query_log='OFF';
RENAME TABLE slow_log TO slow_log2;
set global general_log='ON';
-ERROR HY000: Cannot activate 'general' log
+ERROR 42S02: Table 'mysql.general_log' doesn't exist
set global slow_query_log='ON';
-ERROR HY000: Cannot activate 'slow query' log
+ERROR 42S02: Table 'mysql.slow_log' doesn't exist
RENAME TABLE general_log2 TO general_log;
RENAME TABLE slow_log2 TO slow_log;
set global general_log='ON';
@@ -355,3 +361,71 @@ SET SESSION long_query_time =@old_long_q
FLUSH LOGS;
ALTER TABLE mysql.slow_log DROP COLUMN seq;
ALTER TABLE mysql.slow_log ENGINE = CSV;
+drop procedure if exists proc25422_truncate_slow;
+drop procedure if exists proc25422_truncate_general;
+drop procedure if exists proc25422_alter_slow;
+drop procedure if exists proc25422_alter_general;
+use test//
+create procedure proc25422_truncate_slow (loops int)
+begin
+declare v1 int default 0;
+while v1 < loops do
+truncate mysql.slow_log;
+set v1 = v1 + 1;
+end while;
+end//
+create procedure proc25422_truncate_general (loops int)
+begin
+declare v1 int default 0;
+while v1 < loops do
+truncate mysql.general_log;
+set v1 = v1 + 1;
+end while;
+end//
+create procedure proc25422_alter_slow (loops int)
+begin
+declare v1 int default 0;
+declare ER_BAD_LOG_STATEMENT condition for 1575;
+declare continue handler for ER_BAD_LOG_STATEMENT begin end;
+while v1 < loops do
+set @old_log_state = @@global.slow_query_log;
+set global slow_query_log = 'OFF';
+alter table mysql.slow_log engine = CSV;
+set global slow_query_log = @old_log_state;
+set v1 = v1 + 1;
+end while;
+end//
+create procedure proc25422_alter_general (loops int)
+begin
+declare v1 int default 0;
+declare ER_BAD_LOG_STATEMENT condition for 1575;
+declare continue handler for ER_BAD_LOG_STATEMENT begin end;
+while v1 < loops do
+set @old_log_state = @@global.general_log;
+set global general_log = 'OFF';
+alter table mysql.general_log engine = CSV;
+set global general_log = @old_log_state;
+set v1 = v1 + 1;
+end while;
+end//
+"Serial test (proc25422_truncate_slow)"
+call proc25422_truncate_slow(100);
+"Serial test (proc25422_truncate_general)"
+call proc25422_truncate_general(100);
+"Serial test (proc25422_alter_slow)"
+call proc25422_alter_slow(100);
+"Serial test (proc25422_alter_general)"
+call proc25422_alter_general(100);
+"Parallel test"
+call proc25422_truncate_slow(100);
+call proc25422_truncate_slow(100);
+call proc25422_truncate_general(100);
+call proc25422_truncate_general(100);
+call proc25422_alter_slow(100);
+call proc25422_alter_slow(100);
+call proc25422_alter_general(100);
+call proc25422_alter_general(100);
+drop procedure proc25422_truncate_slow;
+drop procedure proc25422_truncate_general;
+drop procedure proc25422_alter_slow;
+drop procedure proc25422_alter_general;
diff -Nrup a/mysql-test/r/ps.result b/mysql-test/r/ps.result
--- a/mysql-test/r/ps.result 2007-06-07 02:39:10 -06:00
+++ b/mysql-test/r/ps.result 2007-06-28 16:13:39 -06:00
@@ -1850,61 +1850,57 @@ create procedure proc_1() flush tables;
flush tables;
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
flush tables;
@@ -1922,54 +1918,50 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
-mysql host 0 0
mysql user 0 0
+mysql general_log 0 0
+mysql host 0 0
prepare abc from "flush tables";
execute abc;
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
execute abc;
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
execute abc;
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
select Host, User from mysql.user limit 0;
Host User
select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql host 0 0
mysql user 0 0
flush tables;
diff -Nrup a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
--- a/mysql-test/r/show_check.result 2007-06-15 00:53:44 -06:00
+++ b/mysql-test/r/show_check.result 2007-06-28 16:13:39 -06:00
@@ -146,14 +146,13 @@ drop table t1;
flush tables;
show open tables;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
create table t1(n int);
insert into t1 values (1);
show open tables;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
test t1 0 0
drop table t1;
create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1
COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1
ROW_FORMAT=fixed;
@@ -567,24 +566,23 @@ SELECT 1 FROM mysql.db, mysql.proc, mysq
1
SHOW OPEN TABLES;
Database Table In_use Name_locked
-mysql proc 0 0
+mysql db 0 0
test urkunde 0 0
mysql time_zone 0 0
-mysql db 0 0
+mysql general_log 0 0
test txt1 0 0
-mysql slow_log 1 0
+mysql proc 0 0
test tyt2 0 0
-mysql general_log 1 0
mysql user 0 0
mysql time_zone_name 0 0
SHOW OPEN TABLES FROM mysql;
Database Table In_use Name_locked
-mysql proc 0 0
-mysql time_zone 0 0
mysql db 0 0
-mysql slow_log 1 0
-mysql general_log 1 0
+mysql time_zone 0 0
+mysql general_log 0 0
+mysql slow_log 0 0
mysql user 0 0
+mysql proc 0 0
mysql time_zone_name 0 0
SHOW OPEN TABLES FROM mysql LIKE 'u%';
Database Table In_use Name_locked
@@ -597,16 +595,15 @@ test tyt2 0 0
mysql time_zone_name 0 0
SHOW OPEN TABLES LIKE '%o%';
Database Table In_use Name_locked
-mysql proc 0 0
mysql time_zone 0 0
-mysql slow_log 1 0
-mysql general_log 1 0
+mysql general_log 0 0
+mysql slow_log 0 0
+mysql proc 0 0
mysql time_zone_name 0 0
FLUSH TABLES;
SHOW OPEN TABLES;
Database Table In_use Name_locked
-mysql general_log 1 0
-mysql slow_log 1 0
+mysql general_log 0 0
DROP TABLE txt1;
DROP TABLE tyt2;
DROP TABLE urkunde;
diff -Nrup a/mysql-test/r/status.result b/mysql-test/r/status.result
--- a/mysql-test/r/status.result 2007-05-15 01:45:48 -06:00
+++ b/mysql-test/r/status.result 2007-06-28 16:13:39 -06:00
@@ -1,11 +1,11 @@
flush status;
show status like 'Table_lock%';
Variable_name Value
-Table_locks_immediate 0
+Table_locks_immediate 1
Table_locks_waited 0
select * from information_schema.session_status where variable_name like 'Table_lock%';
VARIABLE_NAME VARIABLE_VALUE
-TABLE_LOCKS_IMMEDIATE 0
+TABLE_LOCKS_IMMEDIATE 2
TABLE_LOCKS_WAITED 0
SET SQL_LOG_BIN=0;
drop table if exists t1;
@@ -18,11 +18,11 @@ update t1 set n = 3;
unlock tables;
show status like 'Table_lock%';
Variable_name Value
-Table_locks_immediate 3
+Table_locks_immediate 15
Table_locks_waited 1
select * from information_schema.session_status where variable_name like 'Table_lock%';
VARIABLE_NAME VARIABLE_VALUE
-TABLE_LOCKS_IMMEDIATE 3
+TABLE_LOCKS_IMMEDIATE 16
TABLE_LOCKS_WAITED 1
drop table t1;
select 1;
@@ -97,7 +97,7 @@ Variable_name Value
Com_show_status 3
show status like 'hand%write%';
Variable_name Value
-Handler_write 0
+Handler_write 5
show status like '%tmp%';
Variable_name Value
Created_tmp_disk_tables 0
@@ -105,7 +105,7 @@ Created_tmp_files 0
Created_tmp_tables 0
show status like 'hand%write%';
Variable_name Value
-Handler_write 0
+Handler_write 7
show status like '%tmp%';
Variable_name Value
Created_tmp_disk_tables 0
diff -Nrup a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
--- a/mysql-test/t/disabled.def 2007-06-21 14:07:18 -06:00
+++ b/mysql-test/t/disabled.def 2007-06-28 16:13:39 -06:00
@@ -54,3 +54,7 @@ mysql_upgrade : Bug#28560 test li
rpl_udf : Bug#28993 rpl_udf test causes server crash and valgrind warning in
pushbuild
rpl_ndb_circular : Bug#29233 rpl_ndb_circular fails randomly
ndb_dd_sql_features : Bug#29102 ndb_dd_sql_features fails in pushbuild
+
+## Temporary, to investigate
+rpl_optimize : Marc, OPTIMIZE TABLE dead locks with mysql.general_log
+
diff -Nrup a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test
--- a/mysql-test/t/log_state.test 2007-03-23 06:39:15 -06:00
+++ b/mysql-test/t/log_state.test 2007-06-28 16:13:39 -06:00
@@ -126,6 +126,59 @@ drop table t1;
--replace_column 1 TIMESTAMP 2 USER_HOST 3 #
select * from mysql.general_log;
+#
+# Bug#29129 (Resetting general_log while the GLOBAL READ LOCK is set causes
+# a deadlock)
+
+# save state
+
+SET @old_general_log_state = @@global.general_log;
+set @old_slow_log_state = @@global.slow_query_log;
+
+# Test ON->OFF transition under a GLOBAL READ LOCK
+
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+
+FLUSH TABLES WITH READ LOCK;
+
+SET GLOBAL general_log = OFF;
+SET GLOBAL slow_query_log = OFF;
+
+UNLOCK TABLES;
+
+# Test OFF->ON transition under a GLOBAL READ LOCK
+
+FLUSH TABLES WITH READ LOCK;
+
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+
+UNLOCK TABLES;
+
+# Test ON->OFF transition under a GLOBAL READ_ONLY
+
+SET GLOBAL READ_ONLY = ON;
+
+SET GLOBAL general_log = OFF;
+SET GLOBAL slow_query_log = OFF;
+
+SET GLOBAL READ_ONLY = OFF;
+
+# Test OFF->ON transition under a GLOBAL READ_ONLY
+
+SET GLOBAL READ_ONLY = ON;
+
+SET GLOBAL general_log = ON;
+SET GLOBAL slow_query_log = ON;
+
+SET GLOBAL READ_ONLY = OFF;
+
+# Restore state
+
+SET GLOBAL general_log = @old_general_log_state;
+SET GLOBAL slow_query_log = @old_slow_log_state;
+
--enable_ps_protocol
#
diff -Nrup a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test
--- a/mysql-test/t/log_tables.test 2007-06-13 17:34:41 -06:00
+++ b/mysql-test/t/log_tables.test 2007-06-28 16:13:39 -06:00
@@ -83,71 +83,44 @@ lock tables mysql.general_log READ;
lock tables mysql.slow_log READ;
#
-# This call should result in TL_READ lock on the log table. This is ok and
-# should pass.
+# This call should result in TL_READ lock on the log table.
+# This is not ok and should fail.
#
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
-unlock tables;
-
#
-# check that FLUSH LOGS waits for all readers of the log table to vanish
+# check that FLUSH LOGS does not flush the log tables
#
-connect (con1,localhost,root,,);
-connect (con2,localhost,root,,);
-
-connection con1;
-
-lock tables mysql.general_log READ LOCAL;
-
-connection con2;
-
-# this should wait for log tables to unlock
-send flush logs;
-
-connection con1;
-
-unlock tables;
-
-# this connection should be alive by the time
-connection con2;
+flush logs;
+flush tables;
-reap;
+SET GLOBAL GENERAL_LOG=ON;
+SET GLOBAL SLOW_QUERY_LOG=ON;
-select "Mark that we woke up from flush logs in the test"
- as "test passed";
+show open tables;
+flush logs;
+show open tables;
#
-# perform the same check for TRUNCATE: it should also wait for readers
-# to disappear
+# check that FLUSH TABLES does flush the log tables
#
-connection con1;
-
-lock tables mysql.general_log READ LOCAL;
-
-connection con2;
-
-# this should wait for log tables to unlock
-send truncate mysql.general_log;
-
-connection con1;
+flush tables;
+# Since the flush is logged, mysql.general_log will be in the cache
+show open tables;
-unlock tables;
-
-# this connection should be alive by the time
-connection con2;
-
-reap;
-
-select "Mark that we woke up from TRUNCATE in the test"
- as "test passed";
+SET GLOBAL GENERAL_LOG=OFF;
+SET GLOBAL SLOW_QUERY_LOG=OFF;
-connection con1;
+flush tables;
+# Here the table cache is empty
+show open tables;
-use test;
+SET GLOBAL GENERAL_LOG=ON;
+SET GLOBAL SLOW_QUERY_LOG=ON;
#
# Bug #16905 Log tables: unicode statements are logged incorrectly
@@ -238,15 +211,6 @@ lock tables mysql.general_log READ;
--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.slow_log READ;
-#
-# This call should result in TL_READ lock on the log table. This is ok and
-# should pass.
-#
-
-lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
-
-unlock tables;
-
# check that we can drop them
set global general_log='OFF';
set global slow_query_log='OFF';
@@ -314,6 +278,7 @@ use test;
flush tables with read lock;
unlock tables;
use mysql;
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables general_log read local, help_category read local;
unlock tables;
@@ -368,9 +333,9 @@ set global slow_query_log='OFF';
RENAME TABLE slow_log TO slow_log2;
# this should fail
---error ER_CANT_ACTIVATE_LOG
+--error ER_NO_SUCH_TABLE
set global general_log='ON';
---error ER_CANT_ACTIVATE_LOG
+--error ER_NO_SUCH_TABLE
set global slow_query_log='ON';
RENAME TABLE general_log2 TO general_log;
@@ -470,8 +435,137 @@ FLUSH LOGS;
ALTER TABLE mysql.slow_log DROP COLUMN seq;
ALTER TABLE mysql.slow_log ENGINE = CSV;
-# kill all connections
-disconnect con1;
-disconnect con2;
+#
+# Bug#25422 (Hang with log tables)
+#
+
+--disable_warnings
+drop procedure if exists proc25422_truncate_slow;
+drop procedure if exists proc25422_truncate_general;
+drop procedure if exists proc25422_alter_slow;
+drop procedure if exists proc25422_alter_general;
+--enable_warnings
+
+delimiter //;
+
+use test//
+create procedure proc25422_truncate_slow (loops int)
+begin
+ declare v1 int default 0;
+ while v1 < loops do
+ truncate mysql.slow_log;
+ set v1 = v1 + 1;
+ end while;
+end//
+
+create procedure proc25422_truncate_general (loops int)
+begin
+ declare v1 int default 0;
+ while v1 < loops do
+ truncate mysql.general_log;
+ set v1 = v1 + 1;
+ end while;
+end//
+
+create procedure proc25422_alter_slow (loops int)
+begin
+ declare v1 int default 0;
+ declare ER_BAD_LOG_STATEMENT condition for 1575;
+ declare continue handler for ER_BAD_LOG_STATEMENT begin end;
+
+ while v1 < loops do
+ set @old_log_state = @@global.slow_query_log;
+ set global slow_query_log = 'OFF';
+ alter table mysql.slow_log engine = CSV;
+ set global slow_query_log = @old_log_state;
+ set v1 = v1 + 1;
+ end while;
+end//
+
+create procedure proc25422_alter_general (loops int)
+begin
+ declare v1 int default 0;
+ declare ER_BAD_LOG_STATEMENT condition for 1575;
+ declare continue handler for ER_BAD_LOG_STATEMENT begin end;
+
+ while v1 < loops do
+ set @old_log_state = @@global.general_log;
+ set global general_log = 'OFF';
+ alter table mysql.general_log engine = CSV;
+ set global general_log = @old_log_state;
+ set v1 = v1 + 1;
+ end while;
+end//
+
+delimiter ;//
+
+--echo "Serial test (proc25422_truncate_slow)"
+call proc25422_truncate_slow(100);
+--echo "Serial test (proc25422_truncate_general)"
+call proc25422_truncate_general(100);
+--echo "Serial test (proc25422_alter_slow)"
+call proc25422_alter_slow(100);
+--echo "Serial test (proc25422_alter_general)"
+call proc25422_alter_general(100);
+
+--echo "Parallel test"
+
+# ER_BAD_LOG_STATEMENT errors will occur,
+# since concurrent threads do SET GLOBAL general_log= ...
+# This is silenced by handlers and will not affect the test
+
+connect (addconroot1, localhost, root,,);
+connect (addconroot2, localhost, root,,);
+connect (addconroot3, localhost, root,,);
+connect (addconroot4, localhost, root,,);
+connect (addconroot5, localhost, root,,);
+connect (addconroot6, localhost, root,,);
+connect (addconroot7, localhost, root,,);
+connect (addconroot8, localhost, root,,);
+
+connection addconroot1;
+send call proc25422_truncate_slow(100);
+connection addconroot2;
+send call proc25422_truncate_slow(100);
+
+connection addconroot3;
+send call proc25422_truncate_general(100);
+connection addconroot4;
+send call proc25422_truncate_general(100);
+
+connection addconroot5;
+send call proc25422_alter_slow(100);
+connection addconroot6;
+send call proc25422_alter_slow(100);
+
+connection addconroot7;
+send call proc25422_alter_general(100);
+connection addconroot8;
+send call proc25422_alter_general(100);
+
+connection addconroot1;
+reap;
+connection addconroot2;
+reap;
+connection addconroot3;
+reap;
+connection addconroot4;
+reap;
+connection addconroot5;
+reap;
+connection addconroot6;
+reap;
+connection addconroot7;
+reap;
+connection addconroot8;
+reap;
+
+connection default;
+
+drop procedure proc25422_truncate_slow;
+drop procedure proc25422_truncate_general;
+drop procedure proc25422_alter_slow;
+drop procedure proc25422_alter_general;
+
--enable_ps_protocol
diff -Nrup a/mysql-test/t/ps.test b/mysql-test/t/ps.test
--- a/mysql-test/t/ps.test 2007-06-14 17:33:40 -06:00
+++ b/mysql-test/t/ps.test 2007-06-28 16:13:39 -06:00
@@ -2018,10 +2018,17 @@ delimiter ;|
select func_1(), func_1(), func_1() from dual;
drop function func_1;
drop procedure proc_1;
+
+# make the output deterministic:
+# the order used in SHOW OPEN TABLES
+# is too much implementation dependent
+--disable_ps_protocol
flush tables;
select Host, User from mysql.user limit 0;
select Host, Db from mysql.host limit 0;
show open tables from mysql;
+--enable_ps_protocol
+
prepare abc from "flush tables";
execute abc;
show open tables from mysql;
diff -Nrup a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
--- a/mysql-test/t/show_check.test 2007-06-16 05:14:06 -06:00
+++ b/mysql-test/t/show_check.test 2007-06-28 16:13:39 -06:00
@@ -402,6 +402,11 @@ drop table if exists t1;
CREATE TABLE txt1(a int);
CREATE TABLE tyt2(a int);
CREATE TABLE urkunde(a int);
+
+# make the output deterministic:
+# the order used in SHOW OPEN TABLES
+# is too much implementation dependent
+--disable_ps_protocol
FLUSH TABLES;
SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone_name,
txt1, tyt2, urkunde LIMIT 0;
SHOW OPEN TABLES;
@@ -411,6 +416,8 @@ SHOW OPEN TABLES LIKE 't%';
SHOW OPEN TABLES LIKE '%o%';
FLUSH TABLES;
SHOW OPEN TABLES;
+--enable_ps_protocol
+
DROP TABLE txt1;
DROP TABLE tyt2;
DROP TABLE urkunde;
diff -Nrup a/sql/handler.cc b/sql/handler.cc
--- a/sql/handler.cc 2007-06-21 09:12:54 -06:00
+++ b/sql/handler.cc 2007-06-28 16:13:39 -06:00
@@ -1516,34 +1516,6 @@ THD *handler::ha_thd(void) const
}
-bool handler::check_if_log_table_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table)
-{
- /*
- Deny locking of the log tables, which is incompatible with
- concurrent insert. The routine is not called if the table is
- being locked from a logger THD (general_log_thd or slow_log_thd)
- or from a privileged thread (see log.cc for details)
- */
- if (table->s->log_table &&
- sql_command != SQLCOM_TRUNCATE &&
- sql_command != SQLCOM_ALTER_TABLE &&
- !(sql_command == SQLCOM_FLUSH &&
- type & REFRESH_LOG) &&
- (table->reginfo.lock_type >= TL_READ_NO_INSERT))
- {
- /*
- The check >= TL_READ_NO_INSERT denies all write locks
- plus the only read lock (TL_READ_NO_INSERT itself)
- */
- table->reginfo.lock_type == TL_READ_NO_INSERT ?
- my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) :
- my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
- return FALSE;
- }
- return TRUE;
-}
-
/** @brief
Open database-handler.
@@ -3680,6 +3652,13 @@ int handler::ha_write_row(uchar *buf)
return error;
return 0;
}
+
+
+int handler::ha_write_row_no_binlog(uchar *buf)
+{
+ return write_row(buf);
+}
+
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h 2007-06-18 04:09:21 -06:00
+++ b/sql/handler.h 2007-06-28 16:13:39 -06:00
@@ -1027,44 +1027,6 @@ public:
{
cached_table_flags= table_flags();
}
- /*
- Check whether a handler allows to lock the table.
-
- SYNOPSIS
- check_if_locking_is_allowed()
- thd Handler of the thread, trying to lock the table
- table Table handler to check
- count Total number of tables to be locked
- current Index of the current table in the list of the tables
- to be locked.
- system_count Pointer to the counter of system tables seen thus
- far.
- called_by_privileged_thread TRUE if called from a logger THD
- (general_log_thd or slow_log_thd)
- or by a privileged thread, which
- has the right to lock log tables.
-
- DESCRIPTION
- Check whether a handler allows to lock the table. For instance,
- MyISAM does not allow to lock mysql.proc along with other tables.
- This limitation stems from the fact that MyISAM does not support
- row-level locking and we have to add this limitation to avoid
- deadlocks.
-
- RETURN
- TRUE Locking is allowed
- FALSE Locking is not allowed. The error was thrown.
- */
- virtual bool check_if_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table,
- uint count, uint current,
- uint *system_count,
- bool called_by_privileged_thread)
- {
- return TRUE;
- }
- bool check_if_log_table_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table);
int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
int update_auto_increment();
@@ -1185,6 +1147,7 @@ public:
*/
int ha_external_lock(THD *thd, int lock_type);
int ha_write_row(uchar * buf);
+ int ha_write_row_no_binlog(uchar * buf);
int ha_update_row(const uchar * old_data, uchar * new_data);
int ha_delete_row(const uchar * buf);
diff -Nrup a/sql/lock.cc b/sql/lock.cc
--- a/sql/lock.cc 2007-06-18 14:13:18 -06:00
+++ b/sql/lock.cc 2007-06-28 16:13:39 -06:00
@@ -117,10 +117,23 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
MYSQL_LOCK *sql_lock;
TABLE *write_lock_used;
int rc;
+ uint i;
+ bool must_honor_global_lock;
+
DBUG_ENTER("mysql_lock_tables");
*need_reopen= FALSE;
+ must_honor_global_lock= false;
+ for (i=0 ; i<count; i++)
+ {
+ if (tables[i]->s->honor_global_locks())
+ {
+ must_honor_global_lock= true;
+ break;
+ }
+ }
+
for (;;)
{
if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
@@ -128,7 +141,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
break;
if (global_read_lock && write_lock_used &&
- ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
+ ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK) &&
+ must_honor_global_lock)
{
/*
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
@@ -151,11 +165,11 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
}
}
- if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
- write_lock_used &&
+ if (write_lock_used &&
opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
- !thd->slave_thread)
+ !thd->slave_thread &&
+ must_honor_global_lock)
{
/*
Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
@@ -703,20 +717,71 @@ static MYSQL_LOCK *get_lock_data(THD *th
uint system_count= 0;
for (i=tables=lock_count=0 ; i < count ; i++)
{
- if (table_ptr[i]->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
+ TABLE *t= table_ptr[i];
+
+ /* Protect against 'fake' partially initialized TABLE_SHARE */
+ DBUG_ASSERT(t->s->table_category != TABLE_UNKNOWN_CATEGORY);
+
+ /*
+ Table I/O to performance schema tables is performed
+ only internally by the server implementation.
+ When a user is requesting a lock, the following
+ constraints are enforced:
+ */
+ if (t->s->require_write_privileges() &&
+ !(thd->options & OPTION_INTERNAL_PRIVILEGE))
+ {
+ /*
+ A user should not be able to prevent writes,
+ since this would be a DOS attack.
+ */
+ if (t->reginfo.lock_type == TL_READ_NO_INSERT)
+ {
+ my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0));
+ DBUG_RETURN(0);
+ }
+ /*
+ A user should not be able to insert arbitrary
+ data into log tables.
+ */
+ if (t->reginfo.lock_type >= TL_READ_NO_INSERT)
+ {
+ my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
+ DBUG_RETURN(0);
+ }
+ /*
+ A user should not be able to hold a lock of any
+ kind in the session, this would be a DOS attack.
+ */
+ if (thd->lex->sql_command == SQLCOM_LOCK_TABLES)
+ {
+ my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0));
+ DBUG_RETURN(0);
+ }
+ }
+
+ if ((t->s->table_category == TABLE_CATEGORY_SYSTEM) &&
+ (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE))
+ {
+ system_count++;
+ }
+
+ if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
{
- tables+=table_ptr[i]->file->lock_count();
+ tables+= t->file->lock_count();
lock_count++;
}
- /*
- Check if we can lock the table. For some tables we cannot do that
- beacause of handler-specific locking issues.
- */
- if (!table_ptr[i]-> file->
- check_if_locking_is_allowed(thd->lex->sql_command, thd->lex->type,
- table_ptr[i], count, i, &system_count,
- logger.is_privileged_thread(thd)))
- DBUG_RETURN(0);
+ }
+
+ /*
+ Locking of system tables is restricted:
+ locking a mix of system and non-system tables in the same lock
+ is prohibited, to prevent contention.
+ */
+ if ((system_count > 0) && (system_count < count))
+ {
+ my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
+ DBUG_RETURN(0);
}
/*
diff -Nrup a/sql/log.cc b/sql/log.cc
--- a/sql/log.cc 2007-06-15 11:36:14 -06:00
+++ b/sql/log.cc 2007-06-28 16:13:39 -06:00
@@ -57,6 +57,27 @@ static int binlog_commit(handlerton *hto
static int binlog_rollback(handlerton *hton, THD *thd, bool all);
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
+class Silence_log_table_errors : public Internal_error_handler
+{
+public:
+ Silence_log_table_errors()
+ {}
+
+ virtual ~Silence_log_table_errors() {}
+
+ virtual bool handle_error(uint sql_errno,
+ MYSQL_ERROR::enum_warning_level level,
+ THD *thd);
+};
+
+bool
+Silence_log_table_errors::handle_error(uint /* sql_errno */,
+ MYSQL_ERROR::enum_warning_level /* level */,
+ THD * /* thd */)
+{
+ return true;
+}
+
sql_print_message_func sql_print_message_handlers[3] =
{
sql_print_information,
@@ -188,6 +209,20 @@ public:
handlerton *binlog_hton;
+bool LOGGER::is_log_table_enabled(uint log_table_type)
+{
+ switch (log_table_type) {
+ case QUERY_LOG_SLOW:
+ return (table_log_handler != NULL) && opt_slow_log;
+ case QUERY_LOG_GENERAL:
+ return (table_log_handler != NULL) && opt_log ;
+ default:
+ DBUG_ASSERT(0);
+ return FALSE; /* make compiler happy */
+ }
+}
+
+
/* Check if a given table is opened log table */
int check_if_log_table(uint db_len, const char *db, uint table_name_len,
const char *table_name, uint check_if_opened)
@@ -200,211 +235,38 @@ int check_if_log_table(uint db_len, cons
if (table_name_len == 11 && !(lower_case_table_names ?
my_strcasecmp(system_charset_info,
table_name, "general_log") :
- strcmp(table_name, "general_log")) &&
- (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL)))
- return QUERY_LOG_GENERAL;
- else
- if (table_name_len == 8 && !(lower_case_table_names ?
- my_strcasecmp(system_charset_info, table_name, "slow_log") :
- strcmp(table_name, "slow_log")) &&
- (!check_if_opened ||logger.is_log_table_enabled(QUERY_LOG_SLOW)))
+ strcmp(table_name, "general_log")))
+ {
+ if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL))
+ return QUERY_LOG_GENERAL;
+ return 0;
+ }
+
+ if (table_name_len == 8 && !(lower_case_table_names ?
+ my_strcasecmp(system_charset_info, table_name, "slow_log") :
+ strcmp(table_name, "slow_log")))
+ {
+ if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_SLOW))
return QUERY_LOG_SLOW;
+ return 0;
+ }
}
return 0;
}
-/*
- Open log table of a given type (general or slow log)
-
- SYNOPSIS
- open_log_table()
-
- log_table_type type of the log table to open: QUERY_LOG_GENERAL
- or QUERY_LOG_SLOW
-
- DESCRIPTION
-
- The function opens a log table and marks it as such. Log tables are open
- during the whole time, while server is running. Except for the moments
- when they have to be reopened: during FLUSH LOGS and TRUNCATE. This
- function is invoked directly only once during startup. All subsequent
- calls happen through reopen_log_table(), which performs additional check.
-
- RETURN
- FALSE - OK
- TRUE - error occured
-*/
-
-bool Log_to_csv_event_handler::open_log_table(uint log_table_type)
-{
- THD *log_thd, *curr= current_thd;
- TABLE_LIST *table;
- bool error= FALSE;
- DBUG_ENTER("open_log_table");
-
- switch (log_table_type) {
- case QUERY_LOG_GENERAL:
- log_thd= general_log_thd;
- table= &general_log;
- /* clean up table before reuse/initial usage */
- bzero((char*) table, sizeof(TABLE_LIST));
- table->alias= table->table_name= (char*) "general_log";
- table->table_name_length= 11;
- break;
- case QUERY_LOG_SLOW:
- log_thd= slow_log_thd;
- table= &slow_log;
- bzero((char*) table, sizeof(TABLE_LIST));
- table->alias= table->table_name= (char*) "slow_log";
- table->table_name_length= 8;
- break;
- default:
- assert(0); // Impossible
- }
-
- /*
- This way we check that appropriate log thd was created ok during
- initialization. We cannot check "is_log_tables_initialized" var, as
- the very initialization is not finished until this function is
- completed in the very first time.
- */
- if (!log_thd)
- {
- DBUG_PRINT("error",("Cannot initialize log tables"));
- DBUG_RETURN(TRUE);
- }
-
- /*
- Set THD's thread_stack. This is needed to perform stack overrun
- check, which is done by some routines (e.g. open_table()).
- In the case we are called by thread, which already has this parameter
- set, we use this value. Otherwise we do a wild guess. This won't help
- to correctly track the stack overrun in these exceptional cases (which
- could probably happen only during startup and shutdown) but at least
- lets us to pass asserts.
- The problem stems from the fact that logger THDs are not real threads.
- */
- if (curr)
- log_thd->thread_stack= curr->thread_stack;
- else
- log_thd->thread_stack= (char*) &log_thd;
-
- log_thd->store_globals();
-
- table->lock_type= TL_WRITE_CONCURRENT_INSERT;
- table->db= log_thd->db;
- table->db_length= log_thd->db_length;
-
- lex_start(log_thd);
- log_thd->clear_error();
- if (simple_open_n_lock_tables(log_thd, table) ||
- table->table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
- table->table->file->ha_rnd_init(0))
- error= TRUE;
- else
- {
- table->table->use_all_columns();
- table->table->locked_by_logger= TRUE;
- table->table->no_replicate= TRUE;
-
- /* Honor next number columns if present */
- table->table->next_number_field= table->table->found_next_number_field;
- }
- /* restore thread settings */
- if (curr)
- curr->store_globals();
- else
- {
- my_pthread_setspecific_ptr(THR_THD, 0);
- my_pthread_setspecific_ptr(THR_MALLOC, 0);
- }
-
- /*
- After a log table was opened, we should clear privileged thread
- flag (which allows locking of a log table by a special thread, usually
- the one who closed log tables temporarily).
- */
- privileged_thread= 0;
- DBUG_RETURN(error);
-}
-
-
Log_to_csv_event_handler::Log_to_csv_event_handler()
{
- /* init artificial THD's */
- general_log_thd= new THD;
- /* logger thread always works with mysql database */
- general_log_thd->db= my_strdup("mysql", MYF(0));
- general_log_thd->db_length= 5;
- general_log.table= 0;
-
- slow_log_thd= new THD;
- /* logger thread always works with mysql database */
- slow_log_thd->db= my_strdup("mysql", MYF(0));;
- slow_log_thd->db_length= 5;
- slow_log.table= 0;
- /* no privileged thread exists at the moment */
- privileged_thread= 0;
}
Log_to_csv_event_handler::~Log_to_csv_event_handler()
{
- /* now cleanup the tables */
- if (general_log_thd)
- {
- delete general_log_thd;
- general_log_thd= NULL;
- }
-
- if (slow_log_thd)
- {
- delete slow_log_thd;
- slow_log_thd= NULL;
- }
-}
-
-
-/*
- Reopen log table of a given type
-
- SYNOPSIS
- reopen_log_table()
-
- log_table_type type of the log table to open: QUERY_LOG_GENERAL
- or QUERY_LOG_SLOW
-
- DESCRIPTION
-
- The function is a wrapper around open_log_table(). It is used during
- FLUSH LOGS and TRUNCATE of the log tables (i.e. when we need to close
- and reopen them). The difference is in the check of the
- logger.is_log_tables_initialized var, which can't be done in
- open_log_table(), as it makes no sense during startup.
-
- NOTE: this code assumes that we have logger mutex locked
-
- RETURN
- FALSE - ok
- TRUE - open_log_table() returned an error
-*/
-
-bool Log_to_csv_event_handler::reopen_log_table(uint log_table_type)
-{
- /* don't open the log table, if it wasn't enabled during startup */
- if (!logger.is_log_tables_initialized)
- return FALSE;
- return open_log_table(log_table_type);
}
void Log_to_csv_event_handler::cleanup()
{
- if (opt_log)
- close_log_table(QUERY_LOG_GENERAL, FALSE);
- if (opt_slow_log)
- close_log_table(QUERY_LOG_SLOW, FALSE);
logger.is_log_tables_initialized= FALSE;
}
@@ -436,49 +298,88 @@ void Log_to_csv_event_handler::cleanup()
*/
bool Log_to_csv_event_handler::
- log_general(time_t event_time, const char *user_host,
+ log_general(THD *thd, time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len,
CHARSET_INFO *client_cs)
{
- TABLE *table= general_log.table;
+ TABLE_LIST table_list;
+ TABLE *table;
+ bool result= true;
+ bool need_close= false;
+ bool need_pop= false;
+ bool need_rnd_end= false;
uint field_index;
+ Silence_log_table_errors error_handler;
+ Open_tables_state open_tables_backup;
+ Field_timestamp *field0;
+ ulonglong save_thd_options;
+ bool save_query_start_used;
+ time_t save_start_time;
+ time_t save_time_after_lock;
+ time_t save_user_time;
+ bool save_time_zone_used;
+
+ save_thd_options= thd->options;
+ thd->options&= ~OPTION_BIN_LOG;
+
+ save_query_start_used= thd->query_start_used;
+ save_start_time= thd->start_time;
+ save_time_after_lock= thd->time_after_lock;
+ save_user_time= thd->user_time;
+ save_time_zone_used= thd->time_zone_used;
+
+ bzero(& table_list, sizeof(TABLE_LIST));
+ table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str;
+ table_list.table_name_length= GENERAL_LOG_NAME.length;
+
+ table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
+
+ table_list.db= MYSQL_SCHEMA_NAME.str;
+ table_list.db_length= MYSQL_SCHEMA_NAME.length;
+
+ table= open_performance_schema_table(thd, & table_list,
+ & open_tables_backup);
+ need_close= true;
+
+ if (!table ||
+ table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
+ table->file->ha_rnd_init(0))
+ goto err;
+
+ need_rnd_end= true;
+
+ /* Honor next number columns if present */
+ table->next_number_field= table->found_next_number_field;
/*
"INSERT INTO general_log" can generate warning sometimes.
- Let's reset warnings from previous queries,
- otherwise warning list can grow too much,
- so thd->query gets spoiled as some point in time,
- and mysql_parse() receives a broken query.
QQ: this problem needs to be studied in more details.
- Probably it's better to suppress warnings in logging INSERTs at all.
- Comment this line and run "cast.test" to see what's happening:
+ Comment this 2 lines and run "cast.test" to see what's happening:
*/
- mysql_reset_errors(table->in_use, 1);
-
- /* below should never happen */
- if (unlikely(!logger.is_log_tables_initialized))
- return FALSE;
+ thd->push_internal_handler(& error_handler);
+ need_pop= true;
/*
NOTE: we do not call restore_record() here, as all fields are
filled by the Logger (=> no need to load default ones).
*/
- /* Set current time. Required for CURRENT_TIMESTAMP to work */
- general_log_thd->start_time= event_time;
-
/*
We do not set a value for table->field[0], as it will use
default value (which is CURRENT_TIMESTAMP).
*/
/* check that all columns exist */
- if (!table->field[1] || !table->field[2] || !table->field[3] ||
- !table->field[4] || !table->field[5])
+ if (table->s->fields < 6)
goto err;
+ DBUG_ASSERT(table->field[0]->type() == MYSQL_TYPE_TIMESTAMP);
+
+ field0= (Field_timestamp*) (table->field[0]);
+ field0->set_time();
+
/* do a write */
if (table->field[1]->store(user_host, user_host_len, client_cs) ||
table->field[2]->store((longlong) thread_id, TRUE) ||
@@ -500,16 +401,32 @@ bool Log_to_csv_event_handler::
table->field[field_index]->set_default();
}
- /* log table entries are not replicated at the moment */
- tmp_disable_binlog(current_thd);
-
- table->file->ha_write_row(table->record[0]);
+ table->file->ha_write_row_no_binlog(table->record[0]);
+ table->file->ha_rnd_end();
+ table->file->ha_release_auto_increment();
+ need_rnd_end= false;
- reenable_binlog(current_thd);
+ result= false;
- return FALSE;
err:
- return TRUE;
+ if (need_rnd_end)
+ {
+ table->file->ha_rnd_end();
+ table->file->ha_release_auto_increment();
+ }
+ if (need_pop)
+ thd->pop_internal_handler();
+ if (need_close)
+ close_performance_schema_table(thd, & open_tables_backup);
+
+ thd->options= save_thd_options;
+
+ thd->query_start_used= save_query_start_used;
+ thd->start_time= save_start_time;
+ thd->time_after_lock= save_time_after_lock;
+ thd->user_time= save_user_time;
+ thd->time_zone_used= save_time_zone_used;
+ return result;
}
@@ -548,34 +465,61 @@ bool Log_to_csv_event_handler::
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len)
{
- /* table variables */
- TABLE *table= slow_log.table;
+ TABLE_LIST table_list;
+ TABLE *table;
+ bool result= true;
+ bool need_close= false;
+ bool need_rnd_end= false;
+ Open_tables_state open_tables_backup;
+ bool save_query_start_used;
+ time_t save_start_time;
+ time_t save_time_after_lock;
+ time_t save_user_time;
+ bool save_time_zone_used;
CHARSET_INFO *client_cs= thd->variables.character_set_client;
- DBUG_ENTER("log_slow");
+ DBUG_ENTER("Log_to_csv_event_handler::log_slow");
- /* below should never happen */
- if (unlikely(!logger.is_log_tables_initialized))
- return FALSE;
+ bzero(& table_list, sizeof(TABLE_LIST));
+ table_list.alias= table_list.table_name= SLOW_LOG_NAME.str;
+ table_list.table_name_length= SLOW_LOG_NAME.length;
+
+ table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
+
+ table_list.db= MYSQL_SCHEMA_NAME.str;
+ table_list.db_length= MYSQL_SCHEMA_NAME.length;
+
+ save_query_start_used= thd->query_start_used;
+ save_start_time= thd->start_time;
+ save_time_after_lock= thd->time_after_lock;
+ save_user_time= thd->user_time;
+ save_time_zone_used= thd->time_zone_used;
+
+ table= open_performance_schema_table(thd, & table_list,
+ & open_tables_backup);
+ need_close= true;
+
+ if (!table ||
+ table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
+ table->file->ha_rnd_init(0))
+ goto err;
+
+ need_rnd_end= true;
+
+ /* Honor next number columns if present */
+ table->next_number_field= table->found_next_number_field;
- /*
- Set start time for CURRENT_TIMESTAMP to the start of the query.
- This will be default value for the field[0]
- */
- slow_log_thd->start_time= query_start_arg;
restore_record(table, s->default_values); // Get empty record
+ /* check that all columns exist */
+ if (table->s->fields < 11)
+ goto err;
+
/*
We do not set a value for table->field[0], as it will use
default value.
*/
- if (!table->field[1] || !table->field[2] || !table->field[3] ||
- !table->field[4] || !table->field[5] || !table->field[6] ||
- !table->field[7] || !table->field[8] || !table->field[9] ||
- !table->field[10])
- goto err;
-
/* store the value */
if (table->field[1]->store(user_host, user_host_len, client_cs))
goto err;
@@ -612,7 +556,6 @@ bool Log_to_csv_event_handler::
table->field[4]->set_null();
table->field[5]->set_null();
}
-
/* fill database field */
if (thd->db)
{
@@ -655,18 +598,67 @@ bool Log_to_csv_event_handler::
goto err;
/* log table entries are not replicated at the moment */
- tmp_disable_binlog(current_thd);
-
- /* write the row */
- table->file->ha_write_row(table->record[0]);
+ tmp_disable_binlog(thd);
+ table->file->ha_write_row_no_binlog(table->record[0]);
+ reenable_binlog(thd);
- reenable_binlog(current_thd);
+ result= false;
- DBUG_RETURN(0);
err:
- DBUG_RETURN(1);
+ if (need_rnd_end)
+ {
+ table->file->ha_rnd_end();
+ table->file->ha_release_auto_increment();
+ }
+ if (need_close)
+ close_performance_schema_table(thd, & open_tables_backup);
+
+ thd->query_start_used= save_query_start_used;
+ thd->start_time= save_start_time;
+ thd->time_after_lock= save_time_after_lock;
+ thd->user_time= save_user_time;
+ thd->time_zone_used= save_time_zone_used;
+ DBUG_RETURN(result);
+}
+
+
+int Log_to_csv_event_handler::
+ activate_log(THD *thd, uint log_table_type)
+{
+ TABLE_LIST table_list;
+ TABLE *table;
+ int result;
+ Open_tables_state open_tables_backup;
+
+ DBUG_ENTER("Log_to_csv_event_handler::activate_log");
+
+ bzero(& table_list, sizeof(TABLE_LIST));
+
+ if (log_table_type == QUERY_LOG_GENERAL)
+ {
+ table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str;
+ table_list.table_name_length= GENERAL_LOG_NAME.length;
+ }
+ else
+ {
+ DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW);
+ table_list.alias= table_list.table_name= SLOW_LOG_NAME.str;
+ table_list.table_name_length= SLOW_LOG_NAME.length;
+ }
+
+ table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
+
+ table_list.db= MYSQL_SCHEMA_NAME.str;
+ table_list.db_length= MYSQL_SCHEMA_NAME.length;
+
+ table= open_performance_schema_table(thd, & table_list,
+ & open_tables_backup);
+ result= (table ? 0 : 1);
+ close_performance_schema_table(thd, & open_tables_backup);
+ DBUG_RETURN(result);
}
+
bool Log_to_csv_event_handler::
log_error(enum loglevel level, const char *format, va_list args)
{
@@ -710,7 +702,7 @@ bool Log_to_file_event_handler::
*/
bool Log_to_file_event_handler::
- log_general(time_t event_time, const char *user_host,
+ log_general(THD *thd, time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len,
@@ -806,12 +798,6 @@ void LOGGER::cleanup_end()
}
-void LOGGER::close_log_table(uint log_table_type, bool lock_in_use)
-{
- table_log_handler->close_log_table(log_table_type, lock_in_use);
-}
-
-
/*
Perform basic log initialization: create file-based log handler and
init error log.
@@ -848,29 +834,6 @@ void LOGGER::init_log_tables()
}
-bool LOGGER::reopen_log_table(uint log_table_type)
-{
- return table_log_handler->reopen_log_table(log_table_type);
-}
-
-bool LOGGER::reopen_log_tables()
-{
- /*
- we use | and not || here, to ensure that both reopen_log_table
- are called, even if the first one fails
- */
- if ((opt_slow_log && logger.reopen_log_table(QUERY_LOG_SLOW)) |
- (opt_log && logger.reopen_log_table(QUERY_LOG_GENERAL)))
- return TRUE;
- return FALSE;
-}
-
-
-void LOGGER::tmp_close_log_tables(THD *thd)
-{
- table_log_handler->tmp_close_log_tables(thd);
-}
-
bool LOGGER::flush_logs(THD *thd)
{
int rc= 0;
@@ -880,18 +843,10 @@ bool LOGGER::flush_logs(THD *thd)
log tables are closed
*/
logger.lock();
- if (logger.is_log_tables_initialized)
- table_log_handler->tmp_close_log_tables(thd); // the locking happens here
/* reopen log files */
file_log_handler->flush();
- /* reopen tables in the case they were enabled */
- if (logger.is_log_tables_initialized)
- {
- if (reopen_log_tables())
- rc= TRUE;
- }
/* end of log flush */
logger.unlock();
return rc;
@@ -1035,7 +990,7 @@ bool LOGGER::general_log_print(THD *thd,
while (*current_handler)
error+= (*current_handler++)->
- log_general(current_time, user_host_buff,
+ log_general(thd, current_time, user_host_buff,
user_host_len, id,
command_name[(uint) command].str,
command_name[(uint) command].length,
@@ -1122,35 +1077,42 @@ void LOGGER::init_general_log(uint gener
bool LOGGER::activate_log_handler(THD* thd, uint log_type)
{
- bool res= 0;
+ bool res= false;
lock();
switch (log_type) {
case QUERY_LOG_SLOW:
if (!opt_slow_log)
{
- if ((res= reopen_log_table(log_type)))
- goto err;
file_log_handler->get_mysql_slow_log()->
open_slow_log(sys_var_slow_log_path.value);
init_slow_log(log_output_options);
- opt_slow_log= TRUE;
+ if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW))
+ {
+ my_error(ER_CANT_ACTIVATE_LOG, MYF(0), "slow query");
+ res= true;
+ }
+ else
+ opt_slow_log= TRUE;
}
break;
case QUERY_LOG_GENERAL:
if (!opt_log)
{
- if ((res= reopen_log_table(log_type)))
- goto err;
file_log_handler->get_mysql_log()->
open_query_log(sys_var_general_log_path.value);
init_general_log(log_output_options);
- opt_log= TRUE;
+ if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL))
+ {
+ my_error(ER_CANT_ACTIVATE_LOG, MYF(0), "general");
+ res= true;
+ }
+ else
+ opt_log= TRUE;
}
break;
default:
DBUG_ASSERT(0);
}
-err:
unlock();
return res;
}
@@ -1158,23 +1120,17 @@ err:
void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
{
- TABLE_LIST *table_list;
my_bool *tmp_opt= 0;
MYSQL_LOG *file_log;
- THD *log_thd;
switch (log_type) {
case QUERY_LOG_SLOW:
- table_list= &table_log_handler->slow_log;
tmp_opt= &opt_slow_log;
file_log= file_log_handler->get_mysql_slow_log();
- log_thd= table_log_handler->slow_log_thd;
break;
case QUERY_LOG_GENERAL:
- table_list= &table_log_handler->general_log;
tmp_opt= &opt_log;
file_log= file_log_handler->get_mysql_log();
- log_thd= table_log_handler->general_log_thd;
break;
default:
assert(0); // Impossible
@@ -1183,81 +1139,17 @@ void LOGGER::deactivate_log_handler(THD
if (!(*tmp_opt))
return;
- if (is_log_tables_initialized)
- lock_and_wait_for_table_name(log_thd, table_list);
lock();
- if (is_log_tables_initialized)
- {
- VOID(pthread_mutex_lock(&LOCK_open));
- close_log_table(log_type, TRUE);
- table_list->table= 0;
- query_cache_invalidate3(log_thd, table_list, 0);
- unlock_table_name(log_thd, table_list);
- VOID(pthread_mutex_unlock(&LOCK_open));
- }
file_log->close(0);
*tmp_opt= FALSE;
unlock();
}
-/*
- Close log tables temporarily. The thread which closed
- them this way can lock them in any mode it needs.
- NOTE: one should call logger.lock() before entering this
- function.
-*/
-void Log_to_csv_event_handler::tmp_close_log_tables(THD *thd)
-{
- TABLE_LIST close_slow_log, close_general_log;
-
- /* fill lists, we will need to perform operations on tables */
- bzero((char*) &close_slow_log, sizeof(TABLE_LIST));
- close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log";
- close_slow_log.table_name_length= 8;
- close_slow_log.db= (char*) "mysql";
- close_slow_log.db_length= 5;
-
- bzero((char*) &close_general_log, sizeof(TABLE_LIST));
- close_general_log.alias= close_general_log.table_name=(char*) "general_log";
- close_general_log.table_name_length= 11;
- close_general_log.db= (char*) "mysql";
- close_general_log.db_length= 5;
-
- privileged_thread= thd;
-
- VOID(pthread_mutex_lock(&LOCK_open));
- /*
- NOTE: in fact, the first parameter used in query_cache_invalidate3()
- could be any non-NULL THD, as the underlying code makes certain
- assumptions about this.
- Here we use one of the logger handler THD's. Simply because it
- seems appropriate.
- */
- if (opt_log)
- {
- close_log_table(QUERY_LOG_GENERAL, TRUE);
- query_cache_invalidate3(general_log_thd, &close_general_log, 0);
- }
- if (opt_slow_log)
- {
- close_log_table(QUERY_LOG_SLOW, TRUE);
- query_cache_invalidate3(general_log_thd, &close_slow_log, 0);
- }
- VOID(pthread_mutex_unlock(&LOCK_open));
-}
-
/* the parameters are unused for the log tables */
bool Log_to_csv_event_handler::init()
{
- /*
- we use | and not || here, to ensure that both open_log_table
- are called, even if the first one fails
- */
- if ((opt_log && open_log_table(QUERY_LOG_GENERAL)) |
- (opt_slow_log && open_log_table(QUERY_LOG_SLOW)))
- return 1;
return 0;
}
@@ -1287,72 +1179,6 @@ int LOGGER::set_handlers(uint error_log_
unlock();
return 0;
-}
-
-
-/*
- Close log table of a given type (general or slow log)
-
- SYNOPSIS
- close_log_table()
-
- log_table_type type of the log table to close: QUERY_LOG_GENERAL
- or QUERY_LOG_SLOW
- lock_in_use Set to TRUE if the caller owns LOCK_open. FALSE otherwise.
-
- DESCRIPTION
-
- The function closes a log table. It is invoked (1) when we need to reopen
- log tables (e.g. FLUSH LOGS or TRUNCATE on the log table is being
- executed) or (2) during shutdown.
-*/
-
-void Log_to_csv_event_handler::
- close_log_table(uint log_table_type, bool lock_in_use)
-{
- THD *log_thd, *curr= current_thd;
- TABLE_LIST *table;
-
- if (!logger.is_log_table_enabled(log_table_type))
- return; /* do nothing */
-
- switch (log_table_type) {
- case QUERY_LOG_GENERAL:
- log_thd= general_log_thd;
- table= &general_log;
- break;
- case QUERY_LOG_SLOW:
- log_thd= slow_log_thd;
- table= &slow_log;
- break;
- default:
- assert(0); // Impossible
- }
-
- /*
- Set thread stack start for the logger thread. See comment in
- open_log_table() for details.
- */
- if (curr)
- log_thd->thread_stack= curr->thread_stack;
- else
- log_thd->thread_stack= (char*) &log_thd;
-
- /* close the table */
- log_thd->store_globals();
- table->table->file->ha_rnd_end();
- table->table->file->ha_release_auto_increment();
- /* discard logger mark before unlock*/
- table->table->locked_by_logger= FALSE;
- close_thread_tables(log_thd, lock_in_use);
-
- if (curr)
- curr->store_globals();
- else
- {
- my_pthread_setspecific_ptr(THR_THD, 0);
- my_pthread_setspecific_ptr(THR_MALLOC, 0);
- }
}
diff -Nrup a/sql/log.h b/sql/log.h
--- a/sql/log.h 2007-06-16 22:56:31 -06:00
+++ b/sql/log.h 2007-06-28 16:13:39 -06:00
@@ -398,7 +398,7 @@ public:
const char *sql_text, uint sql_text_len)= 0;
virtual bool log_error(enum loglevel level, const char *format,
va_list args)= 0;
- virtual bool log_general(time_t event_time, const char *user_host,
+ virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len,
@@ -412,27 +412,7 @@ int check_if_log_table(uint db_len, cons
class Log_to_csv_event_handler: public Log_event_handler
{
- /*
- We create artificial THD for each of the logs. This is to avoid
- locking issues: we don't want locks on the log tables reside in the
- THD's of the query. The reason is the locking order and duration.
- */
- THD *general_log_thd, *slow_log_thd;
- /*
- This is for the thread, which called tmp_close_log_tables. The thread
- will be allowed to write-lock the log tables (as it explicitly disabled
- logging). This is used for such operations as REPAIR, which require
- exclusive lock on the log tables.
- NOTE: there can be only one priviliged thread, as one should
- lock logger with logger.lock() before calling tmp_close_log_tables().
- So no other thread could get privileged status at the same time.
- */
- THD *privileged_thread;
friend class LOGGER;
- TABLE_LIST general_log, slow_log;
-
-private:
- bool open_log_table(uint log_type);
public:
Log_to_csv_event_handler();
@@ -447,18 +427,13 @@ public:
const char *sql_text, uint sql_text_len);
virtual bool log_error(enum loglevel level, const char *format,
va_list args);
- virtual bool log_general(time_t event_time, const char *user_host,
+ virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len,
- CHARSET_INFO *client_cs);
- void tmp_close_log_tables(THD *thd);
- void close_log_table(uint log_type, bool lock_in_use);
- bool reopen_log_table(uint log_type);
- THD* get_privileged_thread()
- {
- return privileged_thread;
- }
+ CHARSET_INFO *client_cs);
+
+ int activate_log(THD *thd, uint log_type);
};
@@ -484,7 +459,7 @@ public:
const char *sql_text, uint sql_text_len);
virtual bool log_error(enum loglevel level, const char *format,
va_list args);
- virtual bool log_general(time_t event_time, const char *user_host,
+ virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len,
@@ -521,19 +496,7 @@ public:
{}
void lock() { (void) pthread_mutex_lock(&LOCK_logger); }
void unlock() { (void) pthread_mutex_unlock(&LOCK_logger); }
- void tmp_close_log_tables(THD *thd);
- bool is_log_table_enabled(uint log_table_type)
- {
- switch (log_table_type) {
- case QUERY_LOG_SLOW:
- return table_log_handler && table_log_handler->slow_log.table != 0;
- case QUERY_LOG_GENERAL:
- return table_log_handler && table_log_handler->general_log.table != 0;
- default:
- DBUG_ASSERT(0);
- return FALSE; /* make compiler happy */
- }
- }
+ bool is_log_table_enabled(uint log_table_type);
/*
We want to initialize all log mutexes as soon as possible,
but we cannot do it in constructor, as safe_mutex relies on
@@ -543,20 +506,6 @@ public:
void init_base();
void init_log_tables();
bool flush_logs(THD *thd);
- THD *get_general_log_thd()
- {
- if (table_log_handler)
- return (THD *) table_log_handler->general_log_thd;
- else
- return NULL;
- }
- THD *get_slow_log_thd()
- {
- if (table_log_handler)
- return (THD *) table_log_handler->slow_log_thd;
- else
- return NULL;
- }
/* Perform basic logger cleanup. this will leave e.g. error log open. */
void cleanup_base();
/* Free memory. Nothing could be logged after this function is called */
@@ -568,10 +517,6 @@ public:
bool general_log_print(THD *thd,enum enum_server_command command,
const char *format, va_list args);
- void close_log_table(uint log_type, bool lock_in_use);
- bool reopen_log_table(uint log_type);
- bool reopen_log_tables();
-
/* we use this function to setup all enabled log event handlers */
int set_handlers(uint error_log_printer,
uint slow_log_printer,
@@ -592,19 +537,6 @@ public:
if (file_log_handler)
return file_log_handler->get_mysql_log();
return NULL;
- }
- THD* get_privileged_thread()
- {
- if (table_log_handler)
- return table_log_handler->get_privileged_thread();
- else
- return NULL;
- }
- bool is_privileged_thread(THD *thd)
- {
- return thd == get_general_log_thd() ||
- thd == get_slow_log_thd() ||
- thd == get_privileged_thread();
}
};
diff -Nrup a/sql/mysql_priv.h b/sql/mysql_priv.h
--- a/sql/mysql_priv.h 2007-06-21 13:02:10 -06:00
+++ b/sql/mysql_priv.h 2007-06-28 16:13:39 -06:00
@@ -355,6 +355,13 @@ MY_LOCALE *my_locale_by_number(uint numb
*/
#define TMP_TABLE_FORCE_MYISAM (ULL(1) << 32)
+/*
+ Privileged thread, that can perform operations on
+ privileged tables (as defined by require_write_privileges()).
+ Currently, this flag is used to control locking / writing
+ to the mysql.general_log and mysql.slow_log tables.
+*/
+#define OPTION_INTERNAL_PRIVILEGE (ULL(1) << 33) // THD, intern
/*
Maximum length of time zone name that we support
@@ -1121,6 +1128,11 @@ void reset_status_vars();
/* information schema */
extern LEX_STRING INFORMATION_SCHEMA_NAME;
+/* log tables */
+extern LEX_STRING MYSQL_SCHEMA_NAME;
+extern LEX_STRING GENERAL_LOG_NAME;
+extern LEX_STRING SLOW_LOG_NAME;
+
extern const LEX_STRING partition_keywords[];
LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
const char* str, uint length,
@@ -1450,6 +1462,10 @@ bool open_system_tables_for_read(THD *th
void close_system_tables(THD *thd, Open_tables_state *backup);
TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table);
+TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
+ Open_tables_state *backup);
+void close_performance_schema_table(THD *thd, Open_tables_state *backup);
+
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables, bool
have_lock = FALSE);
bool close_cached_connection_tables(THD *thd, bool wait_for_refresh,
LEX_STRING *connect_string,
@@ -1769,7 +1785,6 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
#define MYSQL_LOCK_IGNORE_FLUSH 0x0002
#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0008
-#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0010
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
diff -Nrup a/sql/set_var.cc b/sql/set_var.cc
--- a/sql/set_var.cc 2007-06-18 04:09:22 -06:00
+++ b/sql/set_var.cc 2007-06-28 16:13:39 -06:00
@@ -2051,21 +2051,15 @@ end:
bool sys_var_log_state::update(THD *thd, set_var *var)
{
- bool res= 0;
+ bool res;
pthread_mutex_lock(&LOCK_global_system_variables);
if (!var->save_result.ulong_value)
- logger.deactivate_log_handler(thd, log_type);
- else
{
- if ((res= logger.activate_log_handler(thd, log_type)))
- {
- my_error(ER_CANT_ACTIVATE_LOG, MYF(0),
- log_type == QUERY_LOG_GENERAL ? "general" :
- "slow query");
- goto err;
- }
+ logger.deactivate_log_handler(thd, log_type);
+ res= false;
}
-err:
+ else
+ res= logger.activate_log_handler(thd, log_type);
pthread_mutex_unlock(&LOCK_global_system_variables);
return res;
}
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt 2007-06-18 04:10:32 -06:00
+++ b/sql/share/errmsg.txt 2007-06-28 16:13:40 -06:00
@@ -5908,7 +5908,7 @@ ER_CANT_WRITE_LOCK_LOG_TABLE
eng "You can't write-lock a log table. Only read access is possible"
ger "Eine Log-Tabelle kann nicht schreibgesperrt werden. Es ist ohnehin nur
Lesezugriff mglich"
ER_CANT_READ_LOCK_LOG_TABLE
- eng "You can't use usual read lock with log tables. Try READ LOCAL instead"
+ eng "You can't use locks with log tables."
ger "Log-Tabellen knnen nicht mit normalen Lesesperren gesperrt werden.
Verwenden Sie statt dessen READ LOCAL"
ER_FOREIGN_DUPLICATE_KEY 23000 S1009
eng "Upholding foreign key constraints for table '%.192s', entry '%-.192s', key
%d would lead to a duplicate entry"
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc 2007-06-21 13:02:11 -06:00
+++ b/sql/sql_base.cc 2007-06-28 16:13:39 -06:00
@@ -900,8 +900,7 @@ bool close_cached_tables(THD *thd, bool
bool found=0;
for (TABLE_LIST *table= tables; table; table= table->next_local)
{
- if ((!table->table || !table->table->s->log_table) &&
- remove_table_from_cache(thd, table->db, table->table_name,
+ if (remove_table_from_cache(thd, table->db, table->table_name,
RTFC_OWNED_BY_THD_FLAG))
found=1;
}
@@ -949,8 +948,7 @@ bool close_cached_tables(THD *thd, bool
are employed by CREATE TABLE as in this case table simply does not
exist yet.
*/
- if (!table->s->log_table &&
- (table->needs_reopen_or_name_lock() && table->db_stat))
+ if (table->needs_reopen_or_name_lock() && table->db_stat)
{
found=1;
DBUG_PRINT("signal", ("Waiting for COND_refresh"));
@@ -2393,18 +2391,37 @@ TABLE *open_table(THD *thd, TABLE_LIST *
VOID(pthread_mutex_unlock(&LOCK_open));
}
}
+
+ LEX_STRING db;
+ LEX_STRING alias;
+ db.str= table_list->db;
+ db.length= strlen(table_list->db);
+ alias.str= table_list->alias;
+ alias.length= strlen(table_list->alias);
+ TABLE_CATEGORY table_category= get_table_category(& db, & alias);
+
/*
- No table in the locked tables list. In case of explicit LOCK TABLES
- this can happen if a user did not include the able into the list.
- In case of pre-locked mode locked tables list is generated automatically,
- so we may only end up here if the table did not exist when
- locked tables list was created.
+ Since we don't want to allow explicit LOCK TABLES on performance schema
+ tables, the code falls through and we open these tables from the cache,
+ even under a LOCK TABLES. This does not cause a dead lock, because
+ manipulating TABLE_CATEGORY_PERFORMANCE tables is very restricted.
*/
- if (thd->prelocked_mode == PRELOCKED)
- my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
- else
- my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias);
- DBUG_RETURN(0);
+ if (table_category != TABLE_CATEGORY_PERFORMANCE)
+ {
+ /*
+ No table in the locked tables list. In case of explicit LOCK TABLES
+ this can happen if a user did not include the able into the list.
+ In case of pre-locked mode locked tables list is generated automatically,
+ so we may only end up here if the table did not exist when
+ locked tables list was created.
+ */
+
+ if (thd->prelocked_mode == PRELOCKED)
+ my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
+ else
+ my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias);
+ DBUG_RETURN(0);
+ }
}
/*
@@ -2466,8 +2483,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *
&state))
{
/*
- Here we flush tables marked for flush. However we never flush log
- tables here. They are flushed only on FLUSH LOGS.
+ Here we flush tables marked for flush.
Normally, table->s->version contains the value of
refresh_version from the moment when this table was
(re-)opened and added to the cache.
@@ -2484,7 +2500,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *
c1: name lock t2; -- blocks
c2: open t1; -- blocks
*/
- if (table->needs_reopen_or_name_lock() && !table->s->log_table)
+ if (table->needs_reopen_or_name_lock())
{
DBUG_PRINT("note",
("Found table '%s.%s' with different refresh version",
@@ -2960,10 +2976,9 @@ void close_old_data_files(THD *thd, TABL
for (; table ; table=table->next)
{
/*
- Reopen marked for flush. But close log tables. They are flushed only
- explicitly on FLUSH LOGS
+ Reopen marked for flush.
*/
- if (table->needs_reopen_or_name_lock() && !table->s->log_table)
+ if (table->needs_reopen_or_name_lock())
{
found=1;
if (table->db_stat)
@@ -3010,10 +3025,6 @@ void close_old_data_files(THD *thd, TABL
Wait until all threads has closed the tables in the list
We have also to wait if there is thread that has a lock on this table even
if the table is closed
- NOTE: log tables are handled differently by the logging routines.
- E.g. general_log is always opened and locked by the logger
- and the table handler used by the logger, will be skipped by
- this check.
*/
bool table_is_used(TABLE *table, bool wait_for_name_lock)
@@ -3032,10 +3043,10 @@ bool table_is_used(TABLE *table, bool wa
search= (TABLE*) hash_next(&open_cache, (uchar*) key,
key_length, &state))
{
- DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d "
+ DBUG_PRINT("info", ("share: 0x%lx "
"open_placeholder: %d locked_by_name: %d "
"db_stat: %u version: %lu",
- (ulong) search->s, search->locked_by_logger,
+ (ulong) search->s,
search->open_placeholder, search->locked_by_name,
search->db_stat,
search->s->version));
@@ -3047,12 +3058,9 @@ bool table_is_used(TABLE *table, bool wa
- If we are in flush table and we didn't execute the flush
- If the table engine is open and it's an old version
(We must wait until all engines are shut down to use the table)
- However we fo not wait if we encountered a table, locked by the logger.
- Log tables are managed separately by logging routines.
*/
- if (!search->locked_by_logger &&
- (search->locked_by_name && wait_for_name_lock ||
- (search->is_name_opened() &&
search->needs_reopen_or_name_lock())))
+ if ( (search->locked_by_name && wait_for_name_lock) ||
+ (search->is_name_opened() &&
search->needs_reopen_or_name_lock()))
DBUG_RETURN(1);
}
} while ((table=table->next));
@@ -4127,11 +4135,6 @@ int lock_tables(THD *thd, TABLE_LIST *ta
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
TABLE **start,**ptr;
uint lock_flag= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN;
-
- /* Ignore GLOBAL READ LOCK and GLOBAL READ_ONLY if called from a logger */
- if (logger.is_privileged_thread(thd))
- lock_flag|= (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
- MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY);
if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count)))
DBUG_RETURN(-1);
@@ -7596,7 +7599,7 @@ open_system_tables_for_read(THD *thd, TA
if (!table)
goto error;
- DBUG_ASSERT(table->s->system_table);
+ DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
table->use_all_columns();
table->reginfo.lock_type= tables->lock_type;
@@ -7666,9 +7669,72 @@ open_system_table_for_update(THD *thd, T
TABLE *table= open_ltable(thd, one_table, one_table->lock_type);
if (table)
{
- DBUG_ASSERT(table->s->system_table);
+ DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
+ table->use_all_columns();
+ }
+
+ DBUG_RETURN(table);
+}
+
+TABLE *
+open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
+ Open_tables_state *backup)
+{
+ DBUG_ENTER("open_performance_schema_table");
+
+ thd->reset_n_backup_open_tables_state(backup);
+
+ DBUG_ASSERT((thd->options & OPTION_INTERNAL_PRIVILEGE) == 0);
+ thd->options|= OPTION_INTERNAL_PRIVILEGE;
+
+ TABLE *table= open_ltable(thd, one_table, one_table->lock_type);
+ if (table)
+ {
+ DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_PERFORMANCE);
table->use_all_columns();
+ table->no_replicate= TRUE;
+ table->s->cached_row_logging_check= 0;
}
+ thd->options&= ~OPTION_INTERNAL_PRIVILEGE;
DBUG_RETURN(table);
}
+
+void close_performance_schema_table(THD *thd, Open_tables_state *backup)
+{
+ bool found_old_table;
+
+ if (thd->lock)
+ {
+ /*
+ Note:
+ We do not create explicitly a separate transaction for the
+ performance table I/O, but borrow the current transaction.
+ lock + unlock will autocommit the change done in the
+ performance schema table: this is the expected result.
+ The current transaction should not be affected by this code.
+ TODO: Consider doing a backup of THD::transaction and THD::ha_data
+ in Open_tables_state, to better isolate this.
+ */
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock= 0;
+ }
+
+ safe_mutex_assert_not_owner(&LOCK_open);
+
+ pthread_mutex_lock(&LOCK_open);
+
+ mysql_ha_mark_tables_for_reopen(thd, thd->open_tables);
+
+ found_old_table= false;
+ while (thd->open_tables)
+ found_old_table|= close_thread_table(thd, &thd->open_tables);
+
+ if (found_old_table)
+ broadcast_refresh();
+
+ pthread_mutex_unlock(&LOCK_open);
+
+ thd->restore_backup_open_tables_state(backup);
+}
+
diff -Nrup a/sql/sql_delete.cc b/sql/sql_delete.cc
--- a/sql/sql_delete.cc 2007-06-24 16:33:23 -06:00
+++ b/sql/sql_delete.cc 2007-06-28 16:13:39 -06:00
@@ -900,16 +900,14 @@ bool multi_delete::send_eof()
- If we want to have a name lock on the table on exit without errors.
*/
-bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
+bool mysql_truncate_impl(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
HA_CREATE_INFO create_info;
char path[FN_REFLEN];
TABLE *table;
bool error;
- uint closed_log_tables= 0, lock_logger= 0;
uint path_length;
- uint log_type;
- DBUG_ENTER("mysql_truncate");
+ DBUG_ENTER("mysql_truncate_impl");
bzero((char*) &create_info,sizeof(create_info));
/* If it is a temporary table, close and regenerate it */
@@ -960,18 +958,6 @@ bool mysql_truncate(THD *thd, TABLE_LIST
DBUG_RETURN(TRUE);
}
- log_type= check_if_log_table(table_list->db_length, table_list->db,
- table_list->table_name_length,
- table_list->table_name, 1);
- /* close log tables in use */
- if (log_type)
- {
- lock_logger= 1;
- logger.lock();
- logger.close_log_table(log_type, FALSE);
- closed_log_tables= closed_log_tables | log_type;
- }
-
// Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
// crashes, replacement works. *(path + path_length - reg_ext_length)=
// '\0';
@@ -997,14 +983,6 @@ end:
VOID(pthread_mutex_lock(&LOCK_open));
unlock_table_name(thd, table_list);
VOID(pthread_mutex_unlock(&LOCK_open));
-
- if (opt_slow_log && (closed_log_tables & QUERY_LOG_SLOW))
- logger.reopen_log_table(QUERY_LOG_SLOW);
-
- if (opt_log && (closed_log_tables & QUERY_LOG_GENERAL))
- logger.reopen_log_table(QUERY_LOG_GENERAL);
- if (lock_logger)
- logger.unlock();
}
else if (error)
{
@@ -1030,3 +1008,29 @@ trunc_by_del:
thd->current_stmt_binlog_row_based= save_binlog_row_based;
DBUG_RETURN(error);
}
+
+
+bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
+{
+ uint log_type;
+ bool result;
+
+ log_type= check_if_log_table(table_list->db_length, table_list->db,
+ table_list->table_name_length,
+ table_list->table_name, 0);
+ if (log_type)
+ {
+ DBUG_ASSERT((thd->options & OPTION_INTERNAL_PRIVILEGE) == 0);
+ thd->options|= OPTION_INTERNAL_PRIVILEGE;
+ }
+
+ result= mysql_truncate_impl(thd, table_list, dont_send_ok);
+
+ if (log_type)
+ {
+ thd->options&= ~OPTION_INTERNAL_PRIVILEGE;
+ }
+
+ return result;
+}
+
diff -Nrup a/sql/sql_error.cc b/sql/sql_error.cc
--- a/sql/sql_error.cc 2007-06-07 02:39:27 -06:00
+++ b/sql/sql_error.cc 2007-06-28 16:13:39 -06:00
@@ -137,6 +137,9 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQ
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
}
+ if (thd->handle_error(code, level))
+ DBUG_RETURN(NULL);
+
if (thd->spcont &&
thd->spcont->handle_error(code, level, thd))
{
diff -Nrup a/sql/sql_rename.cc b/sql/sql_rename.cc
--- a/sql/sql_rename.cc 2007-06-19 05:27:52 -06:00
+++ b/sql/sql_rename.cc 2007-06-28 16:13:39 -06:00
@@ -37,7 +37,6 @@ bool mysql_rename_tables(THD *thd, TABLE
TABLE_LIST *ren_table= 0;
int to_table;
char *rename_log_table[2]= {NULL, NULL};
- int disable_logs= 0;
DBUG_ENTER("mysql_rename_tables");
/*
@@ -80,12 +79,6 @@ bool mysql_rename_tables(THD *thd, TABLE
ren_table->table_name, 1)))
{
/*
- Log table encoutered we will need to disable and lock logs
- for duration of rename.
- */
- disable_logs= TRUE;
-
- /*
as we use log_table_rename as an array index, we need it to start
with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2.
So, we shift the value to start with 0;
@@ -136,12 +129,6 @@ bool mysql_rename_tables(THD *thd, TABLE
rename_log_table[1]);
DBUG_RETURN(1);
}
-
- if (disable_logs)
- {
- logger.lock();
- logger.tmp_close_log_tables(thd);
- }
}
VOID(pthread_mutex_lock(&LOCK_open));
@@ -182,13 +169,6 @@ bool mysql_rename_tables(THD *thd, TABLE
err:
pthread_mutex_unlock(&LOCK_open);
- /* enable logging back if needed */
- if (disable_logs)
- {
- if (logger.reopen_log_tables())
- error= TRUE;
- logger.unlock();
- }
start_waiting_global_read_lock(thd);
DBUG_RETURN(error);
}
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc 2007-06-24 20:06:04 -06:00
+++ b/sql/sql_select.cc 2007-06-28 16:13:39 -06:00
@@ -2451,7 +2451,7 @@ make_join_statistics(JOIN *join, TABLE_L
#else
const bool no_partitions_used= FALSE;
#endif
- if ((table->s->system || table->file->stats.records <= 1 ||
+ if ((table->s->one_record_table || table->file->stats.records <= 1 ||
no_partitions_used) &&
!s->dependent &&
(table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
diff -Nrup a/sql/sql_show.cc b/sql/sql_show.cc
--- a/sql/sql_show.cc 2007-06-14 05:37:50 -06:00
+++ b/sql/sql_show.cc 2007-06-28 16:13:39 -06:00
@@ -2166,9 +2166,6 @@ LEX_STRING *make_lex_string(THD *thd, LE
}
-/* INFORMATION_SCHEMA name */
-LEX_STRING INFORMATION_SCHEMA_NAME= { C_STRING_WITH_LEN("information_schema")};
-
/* This is only used internally, but we need it here as a forward reference */
extern ST_SCHEMA_TABLE schema_tables[];
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc 2007-06-19 05:01:05 -06:00
+++ b/sql/sql_table.cc 2007-06-28 16:13:39 -06:00
@@ -1565,7 +1565,7 @@ int mysql_rm_table_part2(THD *thd, TABLE
table->db_type= share->db_type();
/* Disable drop of enabled log tables */
- if (share && share->log_table &&
+ if (share && (share->table_category == TABLE_CATEGORY_PERFORMANCE)
&&
check_if_log_table(table->db_length, table->db,
table->table_name_length, table->table_name, 1))
{
@@ -4067,9 +4067,11 @@ static bool mysql_admin_table(THD* thd,
table->table_name, 1) &&
lock_type >= TL_READ_NO_INSERT)
{
+ DBUG_ASSERT((thd->options & OPTION_INTERNAL_PRIVILEGE) == 0);
+ thd->options|= OPTION_INTERNAL_PRIVILEGE;
+
disable_logs= 1;
logger.lock();
- logger.tmp_close_log_tables(thd);
}
open_and_lock_tables(thd, table);
@@ -4141,8 +4143,7 @@ static bool mysql_admin_table(THD* thd,
}
/* Close all instances of the table to allow repair to rename files */
- if (lock_type == TL_WRITE && table->table->s->version &&
- !table->table->s->log_table)
+ if (lock_type == TL_WRITE && table->table->s->version)
{
pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
@@ -4366,10 +4367,9 @@ send_result_message:
}
if (table->table)
{
- /* in the below check we do not refresh the log tables */
if (fatal_error)
table->table->s->version=0; // Force close of table
- else if (open_for_modify && !table->table->s->log_table)
+ else if (open_for_modify)
{
if (table->table->s->tmp_table)
table->table->file->info(HA_STATUS_CONST);
@@ -4394,9 +4394,8 @@ send_result_message:
send_eof(thd);
if (disable_logs)
{
- if (logger.reopen_log_tables())
- my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
logger.unlock();
+ thd->options&= ~OPTION_INTERNAL_PRIVILEGE;
}
DBUG_RETURN(FALSE);
@@ -4406,9 +4405,8 @@ send_result_message:
/* enable logging back if needed */
if (disable_logs)
{
- if (logger.reopen_log_tables())
- my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
logger.unlock();
+ thd->options&= ~OPTION_INTERNAL_PRIVILEGE;
}
if (table)
table->table=0;
@@ -5658,7 +5656,7 @@ err:
Alter table
SYNOPSIS
- mysql_alter_table()
+ mysql_alter_table_impl()
thd Thread handle
new_db If there is a RENAME clause
new_name If there is a RENAME clause
@@ -5696,7 +5694,7 @@ err:
TRUE Error
*/
-bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
+bool mysql_alter_table_impl(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
@@ -5733,48 +5731,6 @@ bool mysql_alter_table(THD *thd,char *ne
LINT_INIT(index_drop_buffer);
/*
- Check if we attempt to alter mysql.slow_log or
- mysql.general_log table and return an error if
- it is the case.
- TODO: this design is obsolete and will be removed.
- */
- if (table_list && table_list->db && table_list->table_name)
- {
- int table_kind= 0;
-
- table_kind= check_if_log_table(table_list->db_length, table_list->db,
- table_list->table_name_length,
- table_list->table_name, 0);
-
- if (table_kind)
- {
- /* Disable alter of enabled log tables */
- if (logger.is_log_table_enabled(table_kind))
- {
- my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
- DBUG_RETURN(TRUE);
- }
-
- /* Disable alter of log tables to unsupported engine */
- if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
- (!create_info->db_type || /* unknown engine */
- !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
- {
- my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
- DBUG_RETURN(TRUE);
- }
-
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- if (alter_info->flags & ALTER_PARTITION)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
- DBUG_RETURN(TRUE);
- }
-#endif
- }
- }
-
- /*
Assign variables table_name, new_name, db, new_db, path, reg_path
to simplify further comparisions: we want to see if it's a RENAME
later just by comparing the pointers, avoiding the need for strcmp.
@@ -6759,7 +6715,73 @@ err_with_placeholders:
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(TRUE);
}
-/* mysql_alter_table */
+
+
+bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ Alter_info *alter_info,
+ uint order_num, ORDER *order, bool ignore)
+{
+ bool result;
+
+ DBUG_ENTER("mysql_alter_table");
+ DBUG_ASSERT((thd->options & OPTION_INTERNAL_PRIVILEGE) == 0);
+
+ /*
+ Check if we attempt to alter mysql.slow_log or
+ mysql.general_log table and return an error if
+ it is the case.
+ TODO: this design is obsolete and will be removed.
+ */
+ if (table_list && table_list->db && table_list->table_name)
+ {
+ int table_kind= 0;
+
+ table_kind= check_if_log_table(table_list->db_length, table_list->db,
+ table_list->table_name_length,
+ table_list->table_name, 0);
+
+ if (table_kind)
+ {
+ /* Disable alter of enabled log tables */
+ if (logger.is_log_table_enabled(table_kind))
+ {
+ my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
+ DBUG_RETURN(TRUE);
+ }
+
+ /* Disable alter of log tables to unsupported engine */
+ if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
+ (!create_info->db_type || /* unknown engine */
+ !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
+ {
+ my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (alter_info->flags & ALTER_PARTITION)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
+ DBUG_RETURN(TRUE);
+ }
+#endif
+
+ DBUG_ASSERT((thd->options & OPTION_INTERNAL_PRIVILEGE) == 0);
+ thd->options|= OPTION_INTERNAL_PRIVILEGE;
+ }
+ }
+
+ result= mysql_alter_table_impl(thd, new_db, new_name, create_info,
+ table_list, alter_info, order_num,
+ order, ignore);
+
+ thd->options&= ~OPTION_INTERNAL_PRIVILEGE;
+
+ DBUG_RETURN(result);
+}
+
static int
copy_data_between_tables(TABLE *from,TABLE *to,
diff -Nrup a/sql/table.cc b/sql/table.cc
--- a/sql/table.cc 2007-06-25 03:22:22 -06:00
+++ b/sql/table.cc 2007-06-28 16:13:40 -06:00
@@ -21,6 +21,18 @@
#include <m_ctype.h>
#include "md5.h"
+/* INFORMATION_SCHEMA name */
+LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};
+
+/* MYSQL_SCHEMA name */
+LEX_STRING MYSQL_SCHEMA_NAME= {C_STRING_WITH_LEN("mysql")};
+
+/* GENERAL_LOG name */
+LEX_STRING GENERAL_LOG_NAME= {C_STRING_WITH_LEN("general_log")};
+
+/* SLOW_LOG name */
+LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
+
/* Functions defined in this file */
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
@@ -31,6 +43,7 @@ static void fix_type_pointers(const char
uint types, char **names);
static uint find_field(Field **fields, uchar *record, uint start, uint length);
+inline bool is_system_table_name(const char *name, uint length);
/* Get column name from column hash */
@@ -73,6 +86,50 @@ char *fn_rext(char *name)
}
+TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
+{
+ DBUG_ASSERT(db != NULL);
+ DBUG_ASSERT(name != NULL);
+
+ if ((db->length == INFORMATION_SCHEMA_NAME.length) &&
+ (my_strcasecmp(system_charset_info,
+ INFORMATION_SCHEMA_NAME.str,
+ db->str) == 0))
+ {
+ return TABLE_CATEGORY_INFORMATION;
+ }
+
+ if ((db->length == MYSQL_SCHEMA_NAME.length) &&
+ (my_strcasecmp(system_charset_info,
+ MYSQL_SCHEMA_NAME.str,
+ db->str) == 0))
+ {
+ if (is_system_table_name(name->str, name->length))
+ {
+ return TABLE_CATEGORY_SYSTEM;
+ }
+
+ if ((name->length == GENERAL_LOG_NAME.length) &&
+ (my_strcasecmp(system_charset_info,
+ GENERAL_LOG_NAME.str,
+ name->str) == 0))
+ {
+ return TABLE_CATEGORY_PERFORMANCE;
+ }
+
+ if ((name->length == SLOW_LOG_NAME.length) &&
+ (my_strcasecmp(system_charset_info,
+ SLOW_LOG_NAME.str,
+ name->str) == 0))
+ {
+ return TABLE_CATEGORY_PERFORMANCE;
+ }
+ }
+
+ return TABLE_CATEGORY_USER;
+}
+
+
/*
Allocate a setup TABLE_SHARE structure
@@ -177,7 +234,8 @@ void init_tmp_table_share(TABLE_SHARE *s
bzero((char*) share, sizeof(*share));
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
- share->tmp_table= INTERNAL_TMP_TABLE;
+ share->table_category= TABLE_CATEGORY_TEMPORARY;
+ share->tmp_table= INTERNAL_TMP_TABLE;
share->db.str= (char*) key;
share->db.length= strlen(key);
share->table_cache_key.str= (char*) key;
@@ -425,27 +483,11 @@ int open_table_def(THD *thd, TABLE_SHARE
error= open_binary_frm(thd, share, head, file);
*root_ptr= old_root;
- if (share->db.length == 5 && !(lower_case_table_names ?
- my_strcasecmp(system_charset_info, share->db.str, "mysql") :
- strcmp(share->db.str, "mysql")))
- {
- /*
- We can't mark all tables in 'mysql' database as system since we don't
- allow to lock such tables for writing with any other tables (even with
- other system tables) and some privilege tables need this.
- */
- share->system_table= is_system_table_name(share->table_name.str,
- share->table_name.length);
- if (!share->system_table)
- {
- share->log_table= check_if_log_table(share->db.length, share->db.str,
- share->table_name.length,
- share->table_name.str, 0);
- }
- }
error_given= 1;
}
+ share->table_category= get_table_category(& share->db, &
share->table_name);
+
if (!error)
thd->status_var.opened_shares++;
@@ -647,7 +689,7 @@ static int open_binary_frm(THD *thd, TAB
share->reclength = uint2korr((head+16));
if (*(head+26) == 1)
- share->system= 1; /* one-record-database */
+ share->one_record_table= 1; /* one-record-database */
#ifdef HAVE_CRYPTED_FRM
else if (*(head+26) == 2)
{
diff -Nrup a/sql/table.h b/sql/table.h
--- a/sql/table.h 2007-06-05 13:19:57 -06:00
+++ b/sql/table.h 2007-06-28 16:13:40 -06:00
@@ -108,6 +108,100 @@ class Field_timestamp;
class Field_blob;
class Table_triggers_list;
+
+/**
+ Category of table found in the table share.
+*/
+enum enum_table_category
+{
+ /**
+ Unknown value.
+ */
+ TABLE_UNKNOWN_CATEGORY=0,
+
+ /**
+ Temporary table.
+ The table is visible only in the session.
+ Therefore,
+ - LOCK TABLE <t> FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ do not apply to this table.
+ Temporary tables are not part of the table cache.
+ */
+ TABLE_CATEGORY_TEMPORARY=1,
+
+ /**
+ User table.
+ These tables do honor:
+ - LOCK TABLE <t> FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ User tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_USER=2,
+
+ /**
+ System table, maintained by the server.
+ These tables do honor:
+ - LOCK TABLE <t> FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ Typically, writes to system tables are performed by
+ the server implementation, not explicitly be a user.
+ System tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_SYSTEM=3,
+
+ /**
+ Information schema tables.
+ These tables are an interface provided by the system
+ to inspect the system metadata.
+ These tables do *not* honor:
+ - LOCK TABLE <t> FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ as there is no point in locking explicitely
+ an INFORMATION_SCHEMA table.
+ Nothing is directly written to information schema tables.
+ Note that this value is not used currently,
+ since information schema tables are not shared,
+ but implemented as session specific temporary tables.
+ */
+ /*
+ TODO: Fixing the performance issues of I_S will lead
+ to I_S tables in the table cache, which should use
+ this table type.
+ */
+ TABLE_CATEGORY_INFORMATION=4,
+
+ /**
+ Performance schema tables.
+ These tables are an interface provided by the system
+ to inspect the system performance data.
+ These tables do *not* honor:
+ - LOCK TABLE <t> FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ as there is no point in locking explicitely
+ a PERFORMANCE_SCHEMA table.
+ An example of PERFORMANCE_SCHEMA tables are:
+ - mysql.slow_log
+ - mysql.general_log,
+ which *are* updated even when there is either
+ a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect.
+ User queries do not write directly to these tables
+ (there are exceptions for log tables).
+ The server implementation perform writes.
+ Performance tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_PERFORMANCE=5
+};
+typedef enum enum_table_category TABLE_CATEGORY;
+
+TABLE_CATEGORY get_table_category(const LEX_STRING *db,
+ const LEX_STRING *name);
+
/*
This structure is shared between different table objects. There is one
instance of table share per one table in the database.
@@ -116,6 +210,9 @@ class Table_triggers_list;
typedef struct st_table_share
{
st_table_share() {} /* Remove gcc warning */
+
+ TABLE_CATEGORY table_category;
+
/* hash of field names (contains pointers to elements of field array) */
HASH name_hash; /* hash of field names */
MEM_ROOT mem_root;
@@ -209,7 +306,10 @@ typedef struct st_table_share
uint column_bitmap_size;
uchar frm_version;
bool null_field_first;
- bool system; /* Set if system table (one record) */
+
+ /** Set if system table (one record) */
+ bool one_record_table;
+
bool crypted; /* If .frm file is crypted */
bool db_low_byte_first; /* Portable row format */
bool crashed;
@@ -227,18 +327,6 @@ typedef struct st_table_share
*/
int cached_row_logging_check;
- /*
- TRUE if this is a system table like 'mysql.proc', which we want to be
- able to open and lock even when we already have some tables open and
- locked. To avoid deadlocks we have to put certain restrictions on
- locking of this table for writing. FALSE - otherwise.
- */
- bool system_table;
- /*
- This flag is set for the log tables. Used during FLUSH instances to skip
- log tables, while closing tables (since logs must be always available)
- */
- bool log_table;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool auto_partitioned;
const char *partition_info;
@@ -302,6 +390,16 @@ typedef struct st_table_share
set_table_cache_key(key_buff, key_length);
}
+ inline bool honor_global_locks()
+ {
+ return ((table_category == TABLE_CATEGORY_USER)
+ || (table_category == TABLE_CATEGORY_SYSTEM));
+ }
+
+ inline bool require_write_privileges()
+ {
+ return (table_category == TABLE_CATEGORY_PERFORMANCE);
+ }
} TABLE_SHARE;
@@ -459,7 +557,6 @@ struct st_table {
not rely on that.
*/
my_bool open_placeholder;
- my_bool locked_by_logger;
my_bool no_replicate;
my_bool locked_by_name;
my_bool fulltext_searched;
diff -Nrup a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
--- a/storage/csv/ha_tina.cc 2007-06-15 00:27:08 -06:00
+++ b/storage/csv/ha_tina.cc 2007-06-28 16:13:40 -06:00
@@ -785,18 +785,6 @@ void ha_tina::update_status()
}
-bool ha_tina::check_if_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table,
- uint count, uint current,
- uint *system_count,
- bool called_by_privileged_thread)
-{
- if (!called_by_privileged_thread)
- return check_if_log_table_locking_is_allowed(sql_command, type, table);
-
- return TRUE;
-}
-
/*
Open a database file. Keep in mind that tables are caches, so
this will not be called for every request. Any sort of positions
diff -Nrup a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
--- a/storage/csv/ha_tina.h 2007-06-12 14:12:35 -06:00
+++ b/storage/csv/ha_tina.h 2007-06-28 16:13:40 -06:00
@@ -127,11 +127,6 @@ public:
*/
ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; }
- virtual bool check_if_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table,
- uint count, uint current,
- uint *system_count,
- bool called_by_logger_thread);
int open(const char *name, int mode, uint open_options);
int close(void);
int write_row(uchar * buf);
diff -Nrup a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
--- a/storage/myisam/ha_myisam.cc 2007-06-18 04:09:22 -06:00
+++ b/storage/myisam/ha_myisam.cc 2007-06-28 16:13:40 -06:00
@@ -607,41 +607,7 @@ err:
#endif /* HAVE_REPLICATION */
-bool ha_myisam::check_if_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table,
- uint count, uint current,
- uint *system_count,
- bool called_by_privileged_thread)
-{
- /*
- To be able to open and lock for reading system tables like 'mysql.proc',
- when we already have some tables opened and locked, and avoid deadlocks
- we have to disallow write-locking of these tables with any other tables.
- */
- if (table->s->system_table &&
- table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE)
- (*system_count)++;
-
- /* 'current' is an index, that's why '<=' below. */
- if (*system_count > 0 && *system_count <= current)
- {
- my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
- return FALSE;
- }
-
- /*
- Deny locking of the log tables, which is incompatible with
- concurrent insert. Unless called from a logger THD (general_log_thd
- or slow_log_thd) or by a privileged thread.
- */
- if (!called_by_privileged_thread)
- return check_if_log_table_locking_is_allowed(sql_command, type, table);
-
- return TRUE;
-}
-
- /* Name is here without an extension */
-
+/* Name is here without an extension */
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
{
MI_KEYDEF *keyinfo;
diff -Nrup a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
--- a/storage/myisam/ha_myisam.h 2007-05-10 03:59:32 -06:00
+++ b/storage/myisam/ha_myisam.h 2007-06-28 16:13:40 -06:00
@@ -60,11 +60,6 @@ class ha_myisam: public handler
uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
uint checksum() const;
- virtual bool check_if_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table,
- uint count, uint current,
- uint *system_count,
- bool called_by_logger_thread);
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(uchar * buf);
| Thread |
|---|
| • bk commit into 5.1 tree (malff:1.2516) BUG#25422 | marc.alff | 28 Jun |