WL#3984 (Revise locking of mysql.general_log and mysql.slow_log)
Bug#25422 (Hang with log tables) Bug 17876 (Truncating mysql.slow_log in a SP after using cursor locks the thread) Bug 23044 (Warnings on flush of a log table) Bug 29129 (Resetting general_log while the GLOBAL READ LOCK is set causes a deadlock) 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. See WL#3984 for details related to the new locking design. Additional changes (misc bugs exposed and fixed): 1) mysqldump which would ignore some tables in dump_all_tables_in_db(), but forget to ignore the same in dump_all_views_in_db(). 2) 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. 3) Internal errors handlers could intercept errors but not warnings (see sql_error.cc). 4) Implementing a nested call to open tables, for the performance schema tables, exposed an existing bug in remove_table_from_cache(), which would perform: in_use->some_tables_deleted=1; against another thread, without any consideration about thread locking. This call inside remove_table_from_cache() was not required anyway, since calling mysql_lock_abort() takes care of aborting -- cleanly -- threads that might hold a lock on a table. This line (in_use->some_tables_deleted=1) has been removed.
This commit is contained in:
parent
cbd6e56ffa
commit
c7bbd8917c
@ -3726,11 +3726,12 @@ static int dump_all_tables_in_db(char *database)
|
||||
{
|
||||
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 */,");
|
||||
}
|
||||
@ -3804,6 +3805,11 @@ static my_bool dump_all_views_in_db(char *database)
|
||||
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;
|
||||
@ -3813,10 +3819,15 @@ static my_bool dump_all_views_in_db(char *database)
|
||||
{
|
||||
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");
|
||||
@ -3830,7 +3841,11 @@ static my_bool dump_all_views_in_db(char *database)
|
||||
/* We shall continue here, if --force was given */
|
||||
}
|
||||
while ((table= getTableName(0)))
|
||||
get_view_structure(table, database);
|
||||
{
|
||||
char *end= strmov(afterdot, table);
|
||||
if (include_table(hash_key, end - hash_key))
|
||||
get_view_structure(table, database);
|
||||
}
|
||||
if (opt_xml)
|
||||
{
|
||||
fputs("</database>\n", md_result_file);
|
||||
|
@ -131,7 +131,7 @@ set global general_log=ON;
|
||||
set global log_output=default;
|
||||
show variables like 'log_output';
|
||||
Variable_name Value
|
||||
log_output TABLE
|
||||
log_output FILE
|
||||
set global general_log=OFF;
|
||||
set global log_output=FILE;
|
||||
truncate table mysql.general_log;
|
||||
@ -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;
|
||||
|
@ -29,30 +29,83 @@ on (mysql.general_log.command_type = join_test.command_type)
|
||||
drop table join_test;
|
||||
flush logs;
|
||||
lock tables mysql.general_log WRITE;
|
||||
ERROR HY000: You can't write-lock a log table. Only read access is possible
|
||||
ERROR HY000: You can't use locks with log tables.
|
||||
lock tables mysql.slow_log WRITE;
|
||||
ERROR HY000: You can't write-lock a log table. Only read access is possible
|
||||
ERROR HY000: You can't use locks with log tables.
|
||||
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.
|
||||
show create table mysql.general_log;
|
||||
Table Create Table
|
||||
general_log CREATE TABLE `general_log` (
|
||||
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext,
|
||||
`thread_id` int(11) DEFAULT NULL,
|
||||
`server_id` int(11) DEFAULT NULL,
|
||||
`command_type` varchar(64) DEFAULT NULL,
|
||||
`argument` mediumtext
|
||||
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
|
||||
show fields from mysql.general_log;
|
||||
Field Type Null Key Default Extra
|
||||
event_time timestamp NO CURRENT_TIMESTAMP
|
||||
user_host mediumtext YES NULL
|
||||
thread_id int(11) YES NULL
|
||||
server_id int(11) YES NULL
|
||||
command_type varchar(64) YES NULL
|
||||
argument mediumtext YES NULL
|
||||
show create table mysql.slow_log;
|
||||
Table Create Table
|
||||
slow_log CREATE TABLE `slow_log` (
|
||||
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext NOT NULL,
|
||||
`query_time` time NOT NULL,
|
||||
`lock_time` time NOT NULL,
|
||||
`rows_sent` int(11) NOT NULL,
|
||||
`rows_examined` int(11) NOT NULL,
|
||||
`db` varchar(512) DEFAULT NULL,
|
||||
`last_insert_id` int(11) DEFAULT NULL,
|
||||
`insert_id` int(11) DEFAULT NULL,
|
||||
`server_id` int(11) DEFAULT NULL,
|
||||
`sql_text` mediumtext NOT NULL
|
||||
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
|
||||
show fields from mysql.slow_log;
|
||||
Field Type Null Key Default Extra
|
||||
start_time timestamp NO CURRENT_TIMESTAMP
|
||||
user_host mediumtext NO
|
||||
query_time time NO
|
||||
lock_time time NO
|
||||
rows_sent int(11) NO
|
||||
rows_examined int(11) NO
|
||||
db varchar(512) YES NULL
|
||||
last_insert_id int(11) YES NULL
|
||||
insert_id int(11) YES NULL
|
||||
server_id int(11) YES NULL
|
||||
sql_text mediumtext NO
|
||||
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 +124,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;
|
||||
@ -158,15 +211,13 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query set global slow_query_log='ON'
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log
|
||||
flush logs;
|
||||
lock tables mysql.general_log WRITE;
|
||||
ERROR HY000: You can't write-lock a log table. Only read access is possible
|
||||
ERROR HY000: You can't use locks with log tables.
|
||||
lock tables mysql.slow_log WRITE;
|
||||
ERROR HY000: You can't write-lock a log table. Only read access is possible
|
||||
ERROR HY000: You can't use locks with log tables.
|
||||
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 +268,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 +310,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 +407,192 @@ SET SESSION long_query_time =@old_long_query_time;
|
||||
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;
|
||||
FLUSH TABLE mysql.general_log;
|
||||
show warnings;
|
||||
Level Code Message
|
||||
FLUSH TABLE mysql.slow_log;
|
||||
show warnings;
|
||||
Level Code Message
|
||||
DROP TABLE IF EXISTS `db_17876.slow_log_data`;
|
||||
DROP TABLE IF EXISTS `db_17876.general_log_data`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`;
|
||||
DROP DATABASE IF EXISTS `db_17876`;
|
||||
CREATE DATABASE db_17876;
|
||||
CREATE TABLE `db_17876.slow_log_data` (
|
||||
`start_time` timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext ,
|
||||
`query_time` time ,
|
||||
`lock_time` time ,
|
||||
`rows_sent` int(11) ,
|
||||
`rows_examined` int(11) ,
|
||||
`db` varchar(512) default NULL,
|
||||
`last_insert_id` int(11) default NULL,
|
||||
`insert_id` int(11) default NULL,
|
||||
`server_id` int(11) default NULL,
|
||||
`sql_text` mediumtext
|
||||
);
|
||||
CREATE TABLE `db_17876.general_log_data` (
|
||||
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext,
|
||||
`thread_id` int(11) DEFAULT NULL,
|
||||
`server_id` int(11) DEFAULT NULL,
|
||||
`command_type` varchar(64) DEFAULT NULL,
|
||||
`argument` mediumtext
|
||||
);
|
||||
CREATE procedure `db_17876.archiveSlowLog`()
|
||||
BEGIN
|
||||
DECLARE start_time, query_time, lock_time CHAR(20);
|
||||
DECLARE user_host MEDIUMTEXT;
|
||||
DECLARE rows_set, rows_examined, last_insert_id, insert_id, server_id INT;
|
||||
DECLARE dbname MEDIUMTEXT;
|
||||
DECLARE sql_text BLOB;
|
||||
DECLARE done INT DEFAULT 0;
|
||||
DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329;
|
||||
DECLARE cur1 CURSOR FOR SELECT * FROM mysql.slow_log;
|
||||
OPEN cur1;
|
||||
REPEAT
|
||||
BEGIN
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1;
|
||||
FETCH cur1 INTO
|
||||
start_time, user_host, query_time, lock_time,
|
||||
rows_set, rows_examined, dbname, last_insert_id,
|
||||
insert_id, server_id, sql_text;
|
||||
END;
|
||||
IF NOT done THEN
|
||||
BEGIN
|
||||
INSERT INTO
|
||||
`db_17876.slow_log_data`
|
||||
VALUES(start_time, user_host, query_time, lock_time, rows_set, rows_examined,
|
||||
dbname, last_insert_id, insert_id, server_id, sql_text);
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
UNTIL done END REPEAT;
|
||||
CLOSE cur1;
|
||||
TRUNCATE mysql.slow_log;
|
||||
END //
|
||||
CREATE procedure `db_17876.archiveGeneralLog`()
|
||||
BEGIN
|
||||
DECLARE event_time CHAR(20);
|
||||
DECLARE user_host, argument MEDIUMTEXT;
|
||||
DECLARE thread_id, server_id INT;
|
||||
DECLARE sql_text BLOB;
|
||||
DECLARE done INT DEFAULT 0;
|
||||
DECLARE command_type VARCHAR(64);
|
||||
DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329;
|
||||
DECLARE cur1 CURSOR FOR SELECT * FROM mysql.general_log;
|
||||
OPEN cur1;
|
||||
REPEAT
|
||||
BEGIN
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1;
|
||||
FETCH cur1 INTO
|
||||
event_time, user_host, thread_id, server_id,
|
||||
command_type, argument;
|
||||
END;
|
||||
IF NOT done THEN
|
||||
BEGIN
|
||||
INSERT INTO
|
||||
`db_17876.general_log_data`
|
||||
VALUES(event_time, user_host, thread_id, server_id,
|
||||
command_type, argument);
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
UNTIL done END REPEAT;
|
||||
CLOSE cur1;
|
||||
TRUNCATE mysql.general_log;
|
||||
END //
|
||||
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;
|
||||
select "put something into general_log";
|
||||
put something into general_log
|
||||
put something into general_log
|
||||
select "... and something more ...";
|
||||
... and something more ...
|
||||
... and something more ...
|
||||
call `db_17876.archiveSlowLog`();
|
||||
call `db_17876.archiveGeneralLog`();
|
||||
SET GLOBAL general_log = OFF;
|
||||
SET GLOBAL slow_query_log = OFF;
|
||||
call `db_17876.archiveSlowLog`();
|
||||
call `db_17876.archiveGeneralLog`();
|
||||
DROP TABLE `db_17876.slow_log_data`;
|
||||
DROP TABLE `db_17876.general_log_data`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`;
|
||||
DROP DATABASE IF EXISTS `db_17876`;
|
||||
SET GLOBAL general_log = @old_general_log_state;
|
||||
SET GLOBAL slow_query_log = @old_slow_log_state;
|
||||
|
@ -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;
|
||||
|
@ -251,14 +251,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;
|
||||
@ -672,24 +671,23 @@ SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone
|
||||
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
|
||||
@ -702,16 +700,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;
|
||||
|
@ -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 17
|
||||
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 18
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
#
|
||||
|
@ -64,10 +64,10 @@ flush logs;
|
||||
# check locking of the log tables
|
||||
#
|
||||
|
||||
--error ER_CANT_WRITE_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.general_log WRITE;
|
||||
|
||||
--error ER_CANT_WRITE_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.slow_log WRITE;
|
||||
|
||||
#
|
||||
@ -76,78 +76,59 @@ lock tables mysql.slow_log WRITE;
|
||||
# tables are always opened and locked by the logger.
|
||||
#
|
||||
|
||||
--error ER_CANT_READ_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.general_log READ;
|
||||
|
||||
--error ER_CANT_READ_LOCK_LOG_TABLE
|
||||
--error ER_CANT_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.
|
||||
# This call should result in TL_READ lock on the log table.
|
||||
# This is not ok and should fail.
|
||||
#
|
||||
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
|
||||
|
||||
unlock tables;
|
||||
# Misc locking tests
|
||||
|
||||
show create table mysql.general_log;
|
||||
show fields from mysql.general_log;
|
||||
|
||||
show create table mysql.slow_log;
|
||||
show fields from mysql.slow_log;
|
||||
|
||||
#
|
||||
# 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,,);
|
||||
flush logs;
|
||||
flush tables;
|
||||
|
||||
connection con1;
|
||||
SET GLOBAL GENERAL_LOG=ON;
|
||||
SET GLOBAL SLOW_QUERY_LOG=ON;
|
||||
|
||||
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;
|
||||
|
||||
reap;
|
||||
|
||||
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;
|
||||
flush tables;
|
||||
# Since the flush is logged, mysql.general_log will be in the cache
|
||||
show open tables;
|
||||
|
||||
lock tables mysql.general_log READ LOCAL;
|
||||
SET GLOBAL GENERAL_LOG=OFF;
|
||||
SET GLOBAL SLOW_QUERY_LOG=OFF;
|
||||
|
||||
connection con2;
|
||||
flush tables;
|
||||
# Here the table cache is empty
|
||||
show open tables;
|
||||
|
||||
# this should wait for log tables to unlock
|
||||
send truncate mysql.general_log;
|
||||
|
||||
connection con1;
|
||||
|
||||
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";
|
||||
|
||||
connection con1;
|
||||
|
||||
use test;
|
||||
SET GLOBAL GENERAL_LOG=ON;
|
||||
SET GLOBAL SLOW_QUERY_LOG=ON;
|
||||
|
||||
#
|
||||
# Bug #16905 Log tables: unicode statements are logged incorrectly
|
||||
@ -220,10 +201,10 @@ flush logs;
|
||||
|
||||
# check locking of myisam-based log tables
|
||||
|
||||
--error ER_CANT_WRITE_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.general_log WRITE;
|
||||
|
||||
--error ER_CANT_WRITE_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.slow_log WRITE;
|
||||
|
||||
#
|
||||
@ -232,21 +213,12 @@ lock tables mysql.slow_log WRITE;
|
||||
# tables are always opened and locked by the logger.
|
||||
#
|
||||
|
||||
--error ER_CANT_READ_LOCK_LOG_TABLE
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables mysql.general_log READ;
|
||||
|
||||
--error ER_CANT_READ_LOCK_LOG_TABLE
|
||||
--error ER_CANT_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 +286,7 @@ use test;
|
||||
flush tables with read lock;
|
||||
unlock tables;
|
||||
use mysql;
|
||||
--error ER_CANT_LOCK_LOG_TABLE
|
||||
lock tables general_log read local, help_category read local;
|
||||
unlock tables;
|
||||
|
||||
@ -368,9 +341,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 +443,305 @@ 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;
|
||||
|
||||
disconnect addconroot1;
|
||||
disconnect addconroot2;
|
||||
disconnect addconroot3;
|
||||
disconnect addconroot4;
|
||||
disconnect addconroot5;
|
||||
disconnect addconroot6;
|
||||
disconnect addconroot7;
|
||||
disconnect addconroot8;
|
||||
|
||||
drop procedure proc25422_truncate_slow;
|
||||
drop procedure proc25422_truncate_general;
|
||||
drop procedure proc25422_alter_slow;
|
||||
drop procedure proc25422_alter_general;
|
||||
|
||||
--enable_ps_protocol
|
||||
|
||||
|
||||
#
|
||||
# Bug#23044 (Warnings on flush of a log table)
|
||||
#
|
||||
|
||||
FLUSH TABLE mysql.general_log;
|
||||
show warnings;
|
||||
|
||||
FLUSH TABLE mysql.slow_log;
|
||||
show warnings;
|
||||
|
||||
#
|
||||
# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the
|
||||
# thread)
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS `db_17876.slow_log_data`;
|
||||
DROP TABLE IF EXISTS `db_17876.general_log_data`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`;
|
||||
DROP DATABASE IF EXISTS `db_17876`;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE db_17876;
|
||||
|
||||
CREATE TABLE `db_17876.slow_log_data` (
|
||||
`start_time` timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext ,
|
||||
`query_time` time ,
|
||||
`lock_time` time ,
|
||||
`rows_sent` int(11) ,
|
||||
`rows_examined` int(11) ,
|
||||
`db` varchar(512) default NULL,
|
||||
`last_insert_id` int(11) default NULL,
|
||||
`insert_id` int(11) default NULL,
|
||||
`server_id` int(11) default NULL,
|
||||
`sql_text` mediumtext
|
||||
);
|
||||
|
||||
CREATE TABLE `db_17876.general_log_data` (
|
||||
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext,
|
||||
`thread_id` int(11) DEFAULT NULL,
|
||||
`server_id` int(11) DEFAULT NULL,
|
||||
`command_type` varchar(64) DEFAULT NULL,
|
||||
`argument` mediumtext
|
||||
);
|
||||
|
||||
DELIMITER //;
|
||||
|
||||
CREATE procedure `db_17876.archiveSlowLog`()
|
||||
BEGIN
|
||||
DECLARE start_time, query_time, lock_time CHAR(20);
|
||||
DECLARE user_host MEDIUMTEXT;
|
||||
DECLARE rows_set, rows_examined, last_insert_id, insert_id, server_id INT;
|
||||
DECLARE dbname MEDIUMTEXT;
|
||||
DECLARE sql_text BLOB;
|
||||
DECLARE done INT DEFAULT 0;
|
||||
DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329;
|
||||
|
||||
DECLARE cur1 CURSOR FOR SELECT * FROM mysql.slow_log;
|
||||
|
||||
OPEN cur1;
|
||||
|
||||
REPEAT
|
||||
BEGIN
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1;
|
||||
|
||||
FETCH cur1 INTO
|
||||
start_time, user_host, query_time, lock_time,
|
||||
rows_set, rows_examined, dbname, last_insert_id,
|
||||
insert_id, server_id, sql_text;
|
||||
END;
|
||||
|
||||
IF NOT done THEN
|
||||
BEGIN
|
||||
INSERT INTO
|
||||
`db_17876.slow_log_data`
|
||||
VALUES(start_time, user_host, query_time, lock_time, rows_set, rows_examined,
|
||||
dbname, last_insert_id, insert_id, server_id, sql_text);
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
UNTIL done END REPEAT;
|
||||
|
||||
CLOSE cur1;
|
||||
TRUNCATE mysql.slow_log;
|
||||
END //
|
||||
|
||||
CREATE procedure `db_17876.archiveGeneralLog`()
|
||||
BEGIN
|
||||
DECLARE event_time CHAR(20);
|
||||
DECLARE user_host, argument MEDIUMTEXT;
|
||||
DECLARE thread_id, server_id INT;
|
||||
DECLARE sql_text BLOB;
|
||||
DECLARE done INT DEFAULT 0;
|
||||
DECLARE command_type VARCHAR(64);
|
||||
DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329;
|
||||
|
||||
DECLARE cur1 CURSOR FOR SELECT * FROM mysql.general_log;
|
||||
|
||||
OPEN cur1;
|
||||
|
||||
REPEAT
|
||||
BEGIN
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1;
|
||||
|
||||
FETCH cur1 INTO
|
||||
event_time, user_host, thread_id, server_id,
|
||||
command_type, argument;
|
||||
END;
|
||||
|
||||
IF NOT done THEN
|
||||
BEGIN
|
||||
INSERT INTO
|
||||
`db_17876.general_log_data`
|
||||
VALUES(event_time, user_host, thread_id, server_id,
|
||||
command_type, argument);
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
UNTIL done END REPEAT;
|
||||
|
||||
CLOSE cur1;
|
||||
TRUNCATE mysql.general_log;
|
||||
END //
|
||||
|
||||
DELIMITER ;//
|
||||
|
||||
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;
|
||||
|
||||
select "put something into general_log";
|
||||
select "... and something more ...";
|
||||
|
||||
call `db_17876.archiveSlowLog`();
|
||||
call `db_17876.archiveGeneralLog`();
|
||||
|
||||
SET GLOBAL general_log = OFF;
|
||||
SET GLOBAL slow_query_log = OFF;
|
||||
|
||||
call `db_17876.archiveSlowLog`();
|
||||
call `db_17876.archiveGeneralLog`();
|
||||
|
||||
DROP TABLE `db_17876.slow_log_data`;
|
||||
DROP TABLE `db_17876.general_log_data`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`;
|
||||
DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`;
|
||||
DROP DATABASE IF EXISTS `db_17876`;
|
||||
|
||||
SET GLOBAL general_log = @old_general_log_state;
|
||||
SET GLOBAL slow_query_log = @old_slow_log_state;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -438,6 +438,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;
|
||||
@ -447,6 +452,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;
|
||||
|
@ -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.
|
||||
|
||||
@ -3681,6 +3653,18 @@ int handler::ha_write_row(uchar *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Write a record to the engine bypassing row-level binary logging.
|
||||
This method is used internally by the server for writing to
|
||||
performance schema tables, which are never replicated.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
int error;
|
||||
|
@ -1035,44 +1035,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();
|
||||
@ -1196,6 +1158,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);
|
||||
|
||||
|
76
sql/lock.cc
76
sql/lock.cc
@ -117,9 +117,64 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
|
||||
MYSQL_LOCK *sql_lock;
|
||||
TABLE *write_lock_used;
|
||||
int rc;
|
||||
uint i;
|
||||
bool log_table_write_query;
|
||||
uint system_count;
|
||||
|
||||
DBUG_ENTER("mysql_lock_tables");
|
||||
|
||||
*need_reopen= FALSE;
|
||||
system_count= 0;
|
||||
|
||||
log_table_write_query= (is_log_table_write_query(thd->lex->sql_command)
|
||||
|| ((flags & MYSQL_LOCK_PERF_SCHEMA) != 0));
|
||||
|
||||
for (i=0 ; i<count; i++)
|
||||
{
|
||||
TABLE *t= tables[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() &&
|
||||
! log_table_write_query)
|
||||
{
|
||||
/*
|
||||
A user should not be able to prevent writes,
|
||||
or hold any type of lock in a session,
|
||||
since this would be a DOS attack.
|
||||
*/
|
||||
if ((t->reginfo.lock_type >= TL_READ_NO_INSERT)
|
||||
|| (thd->lex->sql_command == SQLCOM_LOCK_TABLES))
|
||||
{
|
||||
my_error(ER_CANT_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++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -439,7 +494,8 @@ void mysql_lock_downgrade_write(THD *thd, TABLE *table,
|
||||
{
|
||||
MYSQL_LOCK *locked;
|
||||
TABLE *write_lock_used;
|
||||
if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
|
||||
if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
|
||||
&write_lock_used)))
|
||||
{
|
||||
for (uint i=0; i < locked->lock_count; i++)
|
||||
thr_downgrade_write_lock(locked->locks[i], new_lock_type);
|
||||
@ -698,25 +754,19 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
|
||||
TABLE **to, **table_buf;
|
||||
DBUG_ENTER("get_lock_data");
|
||||
|
||||
DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
|
||||
|
||||
DBUG_PRINT("info", ("count %d", count));
|
||||
*write_lock_used=0;
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
732
sql/log.cc
732
sql/log.cc
@ -57,6 +57,35 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all);
|
||||
static int binlog_rollback(handlerton *hton, THD *thd, bool all);
|
||||
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
|
||||
|
||||
/**
|
||||
Silence all errors and warnings reported when performing a write
|
||||
to a log table.
|
||||
Errors and warnings are not reported to the client or SQL exception
|
||||
handlers, so that the presence of logging does not interfere and affect
|
||||
the logic of an application.
|
||||
*/
|
||||
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,
|
||||
@ -187,6 +216,19 @@ 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,
|
||||
@ -200,211 +242,38 @@ int check_if_log_table(uint db_len, const char *db, uint table_name_len,
|
||||
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 +305,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 +408,39 @@ 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);
|
||||
/* log table entries are not replicated */
|
||||
if (table->file->ha_write_row_no_binlog(table->record[0]))
|
||||
{
|
||||
struct tm start;
|
||||
localtime_r(&event_time, &start);
|
||||
|
||||
table->file->ha_write_row(table->record[0]);
|
||||
sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.general_log",
|
||||
start.tm_year % 100, start.tm_mon + 1,
|
||||
start.tm_mday, start.tm_hour,
|
||||
start.tm_min, start.tm_sec);
|
||||
}
|
||||
|
||||
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 +479,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 +570,6 @@ bool Log_to_csv_event_handler::
|
||||
table->field[4]->set_null();
|
||||
table->field[5]->set_null();
|
||||
}
|
||||
|
||||
/* fill database field */
|
||||
if (thd->db)
|
||||
{
|
||||
@ -654,17 +611,71 @@ bool Log_to_csv_event_handler::
|
||||
if (table->field[10]->store(sql_text,sql_text_len, client_cs))
|
||||
goto err;
|
||||
|
||||
/* log table entries are not replicated at the moment */
|
||||
tmp_disable_binlog(current_thd);
|
||||
/* log table entries are not replicated */
|
||||
if (table->file->ha_write_row_no_binlog(table->record[0]))
|
||||
{
|
||||
struct tm start;
|
||||
localtime_r(¤t_time, &start);
|
||||
|
||||
/* write the row */
|
||||
table->file->ha_write_row(table->record[0]);
|
||||
sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.slow_log",
|
||||
start.tm_year % 100, start.tm_mon + 1,
|
||||
start.tm_mday, start.tm_hour,
|
||||
start.tm_min, start.tm_sec);
|
||||
}
|
||||
|
||||
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::
|
||||
@ -697,10 +708,19 @@ bool Log_to_file_event_handler::
|
||||
longlong query_time, longlong lock_time, bool is_command,
|
||||
const char *sql_text, uint sql_text_len)
|
||||
{
|
||||
return mysql_slow_log.write(thd, current_time, query_start_arg,
|
||||
user_host, user_host_len,
|
||||
query_time, lock_time, is_command,
|
||||
sql_text, sql_text_len);
|
||||
bool res;
|
||||
|
||||
(void) pthread_mutex_lock(mysql_slow_log.get_log_lock());
|
||||
|
||||
/* TODO: MYSQL_QUERY_LOG::write is not thread-safe */
|
||||
res= mysql_slow_log.write(thd, current_time, query_start_arg,
|
||||
user_host, user_host_len,
|
||||
query_time, lock_time, is_command,
|
||||
sql_text, sql_text_len);
|
||||
|
||||
(void) pthread_mutex_unlock(mysql_slow_log.get_log_lock());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -710,15 +730,24 @@ 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,
|
||||
CHARSET_INFO *client_cs)
|
||||
{
|
||||
return mysql_log.write(event_time, user_host, user_host_len,
|
||||
thread_id, command_type, command_type_len,
|
||||
sql_text, sql_text_len);
|
||||
bool res;
|
||||
|
||||
(void) pthread_mutex_lock (mysql_log.get_log_lock());
|
||||
|
||||
/* TODO: MYSQL_QUERY_LOG::write is not thread-safe */
|
||||
res= mysql_log.write(event_time, user_host, user_host_len,
|
||||
thread_id, command_type, command_type_len,
|
||||
sql_text, sql_text_len);
|
||||
|
||||
(void) pthread_mutex_unlock (mysql_log.get_log_lock());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -787,7 +816,7 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format,
|
||||
void LOGGER::cleanup_base()
|
||||
{
|
||||
DBUG_ASSERT(inited == 1);
|
||||
(void) pthread_mutex_destroy(&LOCK_logger);
|
||||
rwlock_destroy(&LOCK_logger);
|
||||
if (table_log_handler)
|
||||
{
|
||||
table_log_handler->cleanup();
|
||||
@ -806,12 +835,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.
|
||||
@ -833,7 +856,7 @@ void LOGGER::init_base()
|
||||
init_error_log(LOG_FILE);
|
||||
|
||||
file_log_handler->init_pthread_objects();
|
||||
(void) pthread_mutex_init(&LOCK_logger, MY_MUTEX_INIT_SLOW);
|
||||
my_rwlock_init(&LOCK_logger, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -848,29 +871,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;
|
||||
@ -879,19 +879,11 @@ bool LOGGER::flush_logs(THD *thd)
|
||||
Now we lock logger, as nobody should be able to use logging routines while
|
||||
log tables are closed
|
||||
*/
|
||||
logger.lock();
|
||||
if (logger.is_log_tables_initialized)
|
||||
table_log_handler->tmp_close_log_tables(thd); // the locking happens here
|
||||
logger.lock_exclusive();
|
||||
|
||||
/* 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;
|
||||
@ -939,7 +931,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
|
||||
if (thd->slave_thread)
|
||||
return 0;
|
||||
|
||||
lock();
|
||||
lock_shared();
|
||||
if (!opt_slow_log)
|
||||
{
|
||||
unlock();
|
||||
@ -1011,7 +1003,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
|
||||
else
|
||||
id=0; /* Log from connect handler */
|
||||
|
||||
lock();
|
||||
lock_shared();
|
||||
if (!opt_log)
|
||||
{
|
||||
unlock();
|
||||
@ -1035,7 +1027,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
|
||||
|
||||
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 +1114,42 @@ void LOGGER::init_general_log(uint general_log_printer)
|
||||
|
||||
bool LOGGER::activate_log_handler(THD* thd, uint log_type)
|
||||
{
|
||||
bool res= 0;
|
||||
lock();
|
||||
bool res= FALSE;
|
||||
lock_exclusive();
|
||||
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))
|
||||
{
|
||||
/* Error printed by open table in activate_log() */
|
||||
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))
|
||||
{
|
||||
/* Error printed by open table in activate_log() */
|
||||
res= TRUE;
|
||||
}
|
||||
else
|
||||
opt_log= TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
err:
|
||||
unlock();
|
||||
return res;
|
||||
}
|
||||
@ -1158,23 +1157,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 +1176,16 @@ void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
|
||||
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));
|
||||
}
|
||||
lock_exclusive();
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1268,7 +1196,7 @@ int LOGGER::set_handlers(uint error_log_printer,
|
||||
/* error log table is not supported yet */
|
||||
DBUG_ASSERT(error_log_printer < LOG_TABLE);
|
||||
|
||||
lock();
|
||||
lock_exclusive();
|
||||
|
||||
if ((slow_log_printer & LOG_TABLE || general_log_printer & LOG_TABLE) &&
|
||||
!is_log_tables_initialized)
|
||||
@ -1290,72 +1218,6 @@ int LOGGER::set_handlers(uint error_log_printer,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Save position of binary log transaction cache.
|
||||
|
||||
|
93
sql/log.h
93
sql/log.h
@ -212,6 +212,10 @@ public:
|
||||
return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
|
||||
WRITE_CACHE);
|
||||
}
|
||||
|
||||
/* TODO: fix MYSQL_LOG::write to be thread safe instead. */
|
||||
inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
|
||||
|
||||
private:
|
||||
time_t last_time;
|
||||
};
|
||||
@ -398,7 +402,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 +416,7 @@ int check_if_log_table(uint db_len, const char *db, uint table_name_len,
|
||||
|
||||
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 +431,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 +463,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,
|
||||
@ -499,7 +478,7 @@ public:
|
||||
/* Class which manages slow, general and error log event handlers */
|
||||
class LOGGER
|
||||
{
|
||||
pthread_mutex_t LOCK_logger;
|
||||
rw_lock_t LOCK_logger;
|
||||
/* flag to check whether logger mutex is initialized */
|
||||
uint inited;
|
||||
|
||||
@ -519,21 +498,10 @@ public:
|
||||
LOGGER() : inited(0), table_log_handler(NULL),
|
||||
file_log_handler(NULL), is_log_tables_initialized(FALSE)
|
||||
{}
|
||||
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 */
|
||||
}
|
||||
}
|
||||
void lock_shared() { rw_rdlock(&LOCK_logger); }
|
||||
void lock_exclusive() { rw_wrlock(&LOCK_logger); }
|
||||
void unlock() { rw_unlock(&LOCK_logger); }
|
||||
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 +511,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 +522,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,
|
||||
@ -593,19 +543,6 @@ public:
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
enum enum_binlog_format {
|
||||
|
@ -944,6 +944,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
|
||||
|
||||
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
|
||||
bool is_update_query(enum enum_sql_command command);
|
||||
bool is_log_table_write_query(enum enum_sql_command command);
|
||||
bool alloc_query(THD *thd, const char *packet, uint packet_length);
|
||||
void mysql_init_select(LEX *lex);
|
||||
void mysql_reset_thd_for_next_command(THD *thd);
|
||||
@ -1123,7 +1124,8 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
|
||||
uint key_length, uint db_flags, int *error);
|
||||
void release_table_share(TABLE_SHARE *share, enum release_type type);
|
||||
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name);
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||
uint lock_flags);
|
||||
TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
|
||||
bool *refresh, uint flags);
|
||||
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in);
|
||||
@ -1231,6 +1233,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[];
|
||||
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
|
||||
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx);
|
||||
@ -1557,6 +1564,10 @@ bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
||||
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,
|
||||
@ -1891,6 +1902,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
|
||||
#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
|
||||
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0008
|
||||
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0010
|
||||
#define MYSQL_LOCK_PERF_SCHEMA 0x0020
|
||||
|
||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||
|
@ -2053,21 +2053,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;
|
||||
}
|
||||
@ -2143,7 +2137,7 @@ bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_global_system_variables);
|
||||
logger.lock();
|
||||
logger.lock_exclusive();
|
||||
|
||||
if (file_log && log_state)
|
||||
file_log->close(0);
|
||||
@ -2206,7 +2200,7 @@ static void sys_default_slow_log_path(THD *thd, enum_var_type type)
|
||||
bool sys_var_log_output::update(THD *thd, set_var *var)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_global_system_variables);
|
||||
logger.lock();
|
||||
logger.lock_exclusive();
|
||||
logger.init_slow_log(var->save_result.ulong_value);
|
||||
logger.init_general_log(var->save_result.ulong_value);
|
||||
*value= var->save_result.ulong_value;
|
||||
@ -2219,10 +2213,10 @@ bool sys_var_log_output::update(THD *thd, set_var *var)
|
||||
void sys_var_log_output::set_default(THD *thd, enum_var_type type)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_global_system_variables);
|
||||
logger.lock();
|
||||
logger.init_slow_log(LOG_TABLE);
|
||||
logger.init_general_log(LOG_TABLE);
|
||||
*value= LOG_TABLE;
|
||||
logger.lock_exclusive();
|
||||
logger.init_slow_log(LOG_FILE);
|
||||
logger.init_general_log(LOG_FILE);
|
||||
*value= LOG_FILE;
|
||||
logger.unlock();
|
||||
pthread_mutex_unlock(&LOCK_global_system_variables);
|
||||
}
|
||||
|
@ -5936,8 +5936,8 @@ ER_WARN_DEPRECATED_SYNTAX_WITH_VER
|
||||
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 möglich"
|
||||
ER_CANT_READ_LOCK_LOG_TABLE
|
||||
eng "You can't use usual read lock with log tables. Try READ LOCAL instead"
|
||||
ER_CANT_LOCK_LOG_TABLE
|
||||
eng "You can't use locks with log tables."
|
||||
ger "Log-Tabellen können 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"
|
||||
|
@ -977,7 +977,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
||||
|
||||
thd->proc_info = "Opening master dump table";
|
||||
tables.lock_type = TL_WRITE;
|
||||
if (!open_ltable(thd, &tables, TL_WRITE))
|
||||
if (!open_ltable(thd, &tables, TL_WRITE, 0))
|
||||
{
|
||||
sql_print_error("create_table_from_dump: could not open created table");
|
||||
goto err;
|
||||
|
@ -1067,7 +1067,7 @@ sp_show_status_routine(THD *thd, int type, const char *name_pattern)
|
||||
tables.db= (char*)"mysql";
|
||||
tables.table_name= tables.alias= (char*)"proc";
|
||||
|
||||
if (! (table= open_ltable(thd, &tables, TL_READ)))
|
||||
if (! (table= open_ltable(thd, &tables, TL_READ, 0)))
|
||||
{
|
||||
res= SP_OPEN_TABLE_FAILED;
|
||||
goto done;
|
||||
|
@ -1602,7 +1602,7 @@ bool change_password(THD *thd, const char *host, const char *user,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (!(table= open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
||||
|
130
sql/sql_base.cc
130
sql/sql_base.cc
@ -902,8 +902,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
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;
|
||||
}
|
||||
@ -951,8 +950,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
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"));
|
||||
@ -2468,8 +2466,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
&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.
|
||||
@ -2486,7 +2483,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
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",
|
||||
@ -2962,10 +2959,9 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
|
||||
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)
|
||||
@ -3012,10 +3008,6 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
|
||||
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)
|
||||
@ -3034,10 +3026,10 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||
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));
|
||||
@ -3049,12 +3041,9 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||
- 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));
|
||||
@ -3766,6 +3755,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
|
||||
thd Thread handler
|
||||
table_list Table to open is first table in this list
|
||||
lock_type Lock to use for open
|
||||
lock_flags Flags passed to mysql_lock_table
|
||||
|
||||
NOTE
|
||||
This function don't do anything like SP/SF/views/triggers analysis done
|
||||
@ -3781,7 +3771,8 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
|
||||
table_list->table table
|
||||
*/
|
||||
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
|
||||
uint lock_flags)
|
||||
{
|
||||
TABLE *table;
|
||||
bool refresh;
|
||||
@ -3816,8 +3807,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
{
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
|
||||
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, 0,
|
||||
&refresh)))
|
||||
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1,
|
||||
lock_flags, &refresh)))
|
||||
table= 0;
|
||||
}
|
||||
}
|
||||
@ -4156,11 +4147,6 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
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);
|
||||
@ -7189,7 +7175,6 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
|
||||
else if (in_use != thd)
|
||||
{
|
||||
DBUG_PRINT("info", ("Table was in use by other thread"));
|
||||
in_use->some_tables_deleted=1;
|
||||
if (table->is_name_opened())
|
||||
{
|
||||
DBUG_PRINT("info", ("Found another active instance of the table"));
|
||||
@ -7625,7 +7610,7 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
||||
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;
|
||||
@ -7692,12 +7677,91 @@ open_system_table_for_update(THD *thd, TABLE_LIST *one_table)
|
||||
{
|
||||
DBUG_ENTER("open_system_table_for_update");
|
||||
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type);
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, 0);
|
||||
if (table)
|
||||
{
|
||||
DBUG_ASSERT(table->s->system_table);
|
||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
||||
table->use_all_columns();
|
||||
}
|
||||
|
||||
DBUG_RETURN(table);
|
||||
}
|
||||
|
||||
/**
|
||||
Open a performance schema table.
|
||||
Opening such tables is performed internally in the server
|
||||
implementation, and is a 'nested' open, since some tables
|
||||
might be already opened by the current thread.
|
||||
The thread context before this call is saved, and is restored
|
||||
when calling close_performance_schema_table().
|
||||
@param thd The current thread
|
||||
@param one_table Performance schema table to open
|
||||
@param backup [out] Temporary storage used to save the thread context
|
||||
*/
|
||||
TABLE *
|
||||
open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
|
||||
Open_tables_state *backup)
|
||||
{
|
||||
uint flags= ( MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK
|
||||
| MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY
|
||||
| MYSQL_LOCK_PERF_SCHEMA );
|
||||
|
||||
DBUG_ENTER("open_performance_schema_table");
|
||||
|
||||
thd->reset_n_backup_open_tables_state(backup);
|
||||
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, flags);
|
||||
if (table)
|
||||
{
|
||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_PERFORMANCE);
|
||||
/* Make sure all columns get assigned to a default value */
|
||||
table->use_all_columns();
|
||||
}
|
||||
|
||||
DBUG_RETURN(table);
|
||||
}
|
||||
|
||||
/**
|
||||
Close a performance schema table.
|
||||
The last table opened by open_performance_schema_table()
|
||||
is closed, then the thread context is restored.
|
||||
@param thd The current thread
|
||||
@param backup [in] the context to restore.
|
||||
*/
|
||||
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: Note that if a transactional engine is used for log tables,
|
||||
this code will need to be revised, as a separate transaction
|
||||
might be needed.
|
||||
*/
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock= 0;
|
||||
}
|
||||
|
||||
safe_mutex_assert_not_owner(&LOCK_open);
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2438,6 +2438,7 @@ public:
|
||||
#define CF_HAS_ROW_COUNT 2
|
||||
#define CF_STATUS_COMMAND 4
|
||||
#define CF_SHOW_TABLE_COMMAND 8
|
||||
#define CF_WRITE_LOGS_COMMAND 16
|
||||
|
||||
/* Functions in sql_class.cc */
|
||||
|
||||
|
@ -906,9 +906,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
|
||||
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");
|
||||
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
@ -960,18 +958,6 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
|
||||
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)
|
||||
{
|
||||
|
@ -137,6 +137,9 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
|
||||
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))
|
||||
{
|
||||
|
@ -2254,7 +2254,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
||||
}
|
||||
|
||||
/* open table */
|
||||
if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED)))
|
||||
if (!(di->table=open_ltable(thd, &di->table_list, TL_WRITE_DELAYED, 0)))
|
||||
{
|
||||
thd->fatal_error(); // Abort waiting inserts
|
||||
goto err;
|
||||
|
@ -197,8 +197,8 @@ void init_update_queries(void)
|
||||
|
||||
sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
|
||||
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
|
||||
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA;
|
||||
@ -210,8 +210,8 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
|
||||
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA;
|
||||
|
||||
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
|
||||
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
|
||||
@ -250,6 +250,14 @@ void init_update_queries(void)
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT;
|
||||
sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
|
||||
|
||||
/*
|
||||
The following admin table operations are allowed
|
||||
on log tables.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]= CF_WRITE_LOGS_COMMAND;
|
||||
sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND;
|
||||
}
|
||||
|
||||
|
||||
@ -259,6 +267,17 @@ bool is_update_query(enum enum_sql_command command)
|
||||
return (sql_command_flags[command] & CF_CHANGES_DATA) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if a sql command is allowed to write to log tables.
|
||||
@param command The SQL command
|
||||
@return true if writing is allowed
|
||||
*/
|
||||
bool is_log_table_write_query(enum enum_sql_command command)
|
||||
{
|
||||
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
|
||||
return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0;
|
||||
}
|
||||
|
||||
void execute_init_command(THD *thd, sys_var_str *init_command_var,
|
||||
rw_lock_t *var_mutex)
|
||||
{
|
||||
@ -493,7 +512,7 @@ int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name)
|
||||
if (lower_case_table_names)
|
||||
my_casedn_str(files_charset_info, tbl_name);
|
||||
|
||||
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
|
||||
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT, 0)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (check_one_table_access(thd, SELECT_ACL, table_list))
|
||||
|
@ -1617,7 +1617,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* need to open before acquiring LOCK_plugin or it will deadlock */
|
||||
if (! (table = open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (! (table = open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
pthread_mutex_lock(&LOCK_plugin);
|
||||
@ -1674,7 +1674,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
|
||||
tables.table_name= tables.alias= (char *)"plugin";
|
||||
|
||||
/* need to open before acquiring LOCK_plugin or it will deadlock */
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
pthread_mutex_lock(&LOCK_plugin);
|
||||
|
@ -37,7 +37,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
TABLE_LIST *ren_table= 0;
|
||||
int to_table;
|
||||
char *rename_log_table[2]= {NULL, NULL};
|
||||
int disable_logs= 0;
|
||||
DBUG_ENTER("mysql_rename_tables");
|
||||
|
||||
/*
|
||||
@ -79,12 +78,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
ren_table->table_name_length,
|
||||
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.
|
||||
@ -136,12 +129,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
rename_log_table[1]);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (disable_logs)
|
||||
{
|
||||
logger.lock();
|
||||
logger.tmp_close_log_tables(thd);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
@ -200,13 +187,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
err:
|
||||
/* 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);
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ insert_server(THD *thd, FOREIGN_SERVER *server)
|
||||
tables.alias= tables.table_name= (char*) "servers";
|
||||
|
||||
/* need to open before acquiring THR_LOCK_plugin or it will deadlock */
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
goto end;
|
||||
|
||||
/* insert the server into the table */
|
||||
@ -588,7 +588,7 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
|
||||
if ((error= delete_server_record_in_cache(server_options)))
|
||||
goto end;
|
||||
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (! (table= open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
{
|
||||
error= my_errno;
|
||||
goto end;
|
||||
@ -705,7 +705,7 @@ int update_server(THD *thd, FOREIGN_SERVER *existing, FOREIGN_SERVER *altered)
|
||||
tables.db= (char*)"mysql";
|
||||
tables.alias= tables.table_name= (char*)"servers";
|
||||
|
||||
if (!(table= open_ltable(thd, &tables, TL_WRITE)))
|
||||
if (!(table= open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
{
|
||||
error= my_errno;
|
||||
goto end;
|
||||
|
@ -2176,9 +2176,6 @@ void calc_sum_of_all_status(STATUS_VAR *to)
|
||||
}
|
||||
|
||||
|
||||
/* 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[];
|
||||
|
||||
|
@ -1513,7 +1513,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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))
|
||||
{
|
||||
@ -3966,7 +3966,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
Item *item;
|
||||
Protocol *protocol= thd->protocol;
|
||||
LEX *lex= thd->lex;
|
||||
int result_code, disable_logs= 0;
|
||||
int result_code;
|
||||
DBUG_ENTER("mysql_admin_table");
|
||||
|
||||
if (end_active_trans(thd))
|
||||
@ -4014,22 +4014,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
if (view_operator_func == NULL)
|
||||
table->required_type=FRMTYPE_TABLE;
|
||||
|
||||
/*
|
||||
If we want to perform an admin operation on the log table
|
||||
(E.g. rename) and lock_type >= TL_READ_NO_INSERT disable
|
||||
log tables
|
||||
*/
|
||||
|
||||
if (check_if_log_table(table->db_length, table->db,
|
||||
table->table_name_length,
|
||||
table->table_name, 1) &&
|
||||
lock_type >= TL_READ_NO_INSERT)
|
||||
{
|
||||
disable_logs= 1;
|
||||
logger.lock();
|
||||
logger.tmp_close_log_tables(thd);
|
||||
}
|
||||
|
||||
open_and_lock_tables(thd, table);
|
||||
thd->no_warnings_for_error= 0;
|
||||
table->next_global= save_next_global;
|
||||
@ -4099,8 +4083,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
}
|
||||
|
||||
/* 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,
|
||||
@ -4258,7 +4241,7 @@ send_result_message:
|
||||
close_thread_tables(thd);
|
||||
if (!result_code) // recreation went ok
|
||||
{
|
||||
if ((table->table= open_ltable(thd, table, lock_type)) &&
|
||||
if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
|
||||
((result_code= table->table->file->analyze(thd, check_opt)) > 0))
|
||||
result_code= 0; // analyze went ok
|
||||
}
|
||||
@ -4324,10 +4307,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);
|
||||
@ -4350,24 +4332,11 @@ send_result_message:
|
||||
}
|
||||
|
||||
send_eof(thd);
|
||||
if (disable_logs)
|
||||
{
|
||||
if (logger.reopen_log_tables())
|
||||
my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
|
||||
logger.unlock();
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
err:
|
||||
ha_autocommit_or_rollback(thd, 1);
|
||||
close_thread_tables(thd); // Shouldn't be needed
|
||||
/* enable logging back if needed */
|
||||
if (disable_logs)
|
||||
{
|
||||
if (logger.reopen_log_tables())
|
||||
my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
|
||||
logger.unlock();
|
||||
}
|
||||
if (table)
|
||||
table->table=0;
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -4812,7 +4781,7 @@ mysql_discard_or_import_tablespace(THD *thd,
|
||||
not complain when we lock the table
|
||||
*/
|
||||
thd->tablespace_op= TRUE;
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
|
||||
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
|
||||
{
|
||||
thd->tablespace_op=FALSE;
|
||||
DBUG_RETURN(-1);
|
||||
@ -5728,7 +5697,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (alter_info->flags & ALTER_PARTITION)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
#endif
|
||||
@ -5817,7 +5786,7 @@ view_err:
|
||||
start_waiting_global_read_lock(thd);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
||||
if (!(table=open_ltable(thd, table_list, TL_WRITE_ALLOW_READ, 0)))
|
||||
DBUG_RETURN(TRUE);
|
||||
table->use_all_columns();
|
||||
|
||||
@ -6986,7 +6955,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
strxmov(table_name, table->db ,".", table->table_name, NullS);
|
||||
|
||||
t= table->table= open_ltable(thd, table, TL_READ);
|
||||
t= table->table= open_ltable(thd, table, TL_READ, 0);
|
||||
thd->clear_error(); // these errors shouldn't get client
|
||||
|
||||
protocol->prepare_for_resend();
|
||||
|
@ -472,7 +472,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "func";
|
||||
/* Allow creation of functions even if we can't open func table */
|
||||
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
|
||||
if (!(table = open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
goto err;
|
||||
table->use_all_columns();
|
||||
restore_record(table, s->default_values); // Default values for fields
|
||||
@ -547,7 +547,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
|
||||
bzero((char*) &tables,sizeof(tables));
|
||||
tables.db=(char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "func";
|
||||
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
|
||||
if (!(table = open_ltable(thd, &tables, TL_WRITE, 0)))
|
||||
goto err;
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
|
||||
|
80
sql/table.cc
80
sql/table.cc
@ -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 ***array, TYPELIB *point_to_type,
|
||||
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);
|
||||
|
||||
/**************************************************************************
|
||||
Object_creation_ctx implementation.
|
||||
@ -192,6 +205,49 @@ char *fn_rext(char *name)
|
||||
return name + strlen(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
|
||||
@ -297,7 +353,8 @@ void init_tmp_table_share(TABLE_SHARE *share, const char *key,
|
||||
|
||||
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;
|
||||
@ -544,28 +601,11 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
||||
*root_ptr= &share->mem_root;
|
||||
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++;
|
||||
|
||||
|
120
sql/table.h
120
sql/table.h
@ -140,6 +140,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,
|
||||
- FLUSH TABLES WITH READ LOCK
|
||||
- SET GLOBAL READ_ONLY = ON
|
||||
do not apply to this table.
|
||||
Note that LOCK TABLE <t> FOR READ/WRITE
|
||||
can be used on temporary tables.
|
||||
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.
|
||||
@ -148,6 +242,10 @@ class Table_triggers_list;
|
||||
typedef struct st_table_share
|
||||
{
|
||||
st_table_share() {} /* Remove gcc warning */
|
||||
|
||||
/** Category of this table. */
|
||||
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;
|
||||
@ -259,18 +357,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;
|
||||
@ -334,6 +420,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;
|
||||
|
||||
|
||||
|
@ -786,18 +786,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
|
||||
|
@ -131,11 +131,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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user