mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-34817 Performance schema is not cleared of removed package routines
Package routines are recorded in performance schema as
PROCEDURE/FUNCTION "<package>.<routine>", but dropping a package body
removed only the PACKAGE BODY record, so routine statistics survived
DROP PACKAGE [BODY] and DROP DATABASE.
Drop the routine records of the package together with the package body
record. Also reset statistics of a newly allocated PFS_program (as in
089caf901f), so a reused slot does not inherit stale counters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Raghunandan Bhat
parent
fb641b0cd1
commit
f57a2b97ad
@@ -187,3 +187,138 @@ SET default_storage_engine = performance_schema;
|
||||
CREATE TEMPORARY TABLE t1 (t int);
|
||||
ERROR HY000: Table storage engine 'PERFORMANCE_SCHEMA' does not support the create option 'TEMPORARY'
|
||||
SET @@default_storage_engine = @default_storage_engine_old;
|
||||
#
|
||||
# MDEV-34817 Performance schema is not cleared of removed package routines
|
||||
#
|
||||
SET @save_sql_mode= @@sql_mode;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
FUNCTION f1 RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 1; END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE db1.pkg1x AS BEGIN NULL; END;
|
||||
$$
|
||||
CALL db1.pkg1.p1;
|
||||
SELECT db1.pkg1.f1();
|
||||
db1.pkg1.f1()
|
||||
1
|
||||
CALL db2.pkg1.p1;
|
||||
CALL db1.pkg1x;
|
||||
# Routines executed in another connection must be removed as well
|
||||
connect con1,localhost,root;
|
||||
CALL db1.pkg1.p1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1.f1 1
|
||||
db1 pkg1.p1 2
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
DROP PACKAGE BODY db1.PKG1;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
# Statistics of the re-created routines start from zero
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 1; END;
|
||||
END;
|
||||
$$
|
||||
CALL db1.pkg1.p1;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1.f1 0
|
||||
db1 pkg1.p1 1
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
# CREATE OR REPLACE PACKAGE BODY
|
||||
CREATE OR REPLACE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
# DROP PACKAGE
|
||||
CALL db1.pkg1.p1;
|
||||
DROP PACKAGE db1.pkg1;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
# DROP DATABASE
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
END;
|
||||
$$
|
||||
CALL db1.pkg1.p1;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db1 pkg1.p1 1
|
||||
db1 pkg1x 1
|
||||
db2 pkg1.p1 1
|
||||
DROP DATABASE db1;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
db2 pkg1.p1 1
|
||||
DROP DATABASE db2;
|
||||
SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
object_schema object_name count_star
|
||||
SET sql_mode= @save_sql_mode;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -318,4 +318,103 @@ SET default_storage_engine = performance_schema;
|
||||
--error ER_ILLEGAL_HA_CREATE_OPTION
|
||||
CREATE TEMPORARY TABLE t1 (t int);
|
||||
|
||||
SET @@default_storage_engine = @default_storage_engine_old;
|
||||
SET @@default_storage_engine = @default_storage_engine_old;
|
||||
--echo #
|
||||
--echo # MDEV-34817 Performance schema is not cleared of removed package routines
|
||||
--echo #
|
||||
|
||||
let $q= SELECT object_schema, object_name, count_star
|
||||
FROM performance_schema.events_statements_summary_by_program
|
||||
WHERE object_type IN ('PROCEDURE','FUNCTION') AND
|
||||
object_schema IN ('db1','db2')
|
||||
ORDER BY object_schema, object_name;
|
||||
|
||||
SET @save_sql_mode= @@sql_mode;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
FUNCTION f1 RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 1; END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE db1.pkg1x AS BEGIN NULL; END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CALL db1.pkg1.p1;
|
||||
SELECT db1.pkg1.f1();
|
||||
CALL db2.pkg1.p1;
|
||||
CALL db1.pkg1x;
|
||||
|
||||
--echo # Routines executed in another connection must be removed as well
|
||||
connect con1,localhost,root;
|
||||
CALL db1.pkg1.p1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
eval $q;
|
||||
|
||||
DROP PACKAGE BODY db1.PKG1;
|
||||
eval $q;
|
||||
|
||||
--echo # Statistics of the re-created routines start from zero
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 1; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL db1.pkg1.p1;
|
||||
eval $q;
|
||||
|
||||
--echo # CREATE OR REPLACE PACKAGE BODY
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
FUNCTION f1 RETURN INT AS BEGIN RETURN 2; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
eval $q;
|
||||
|
||||
--echo # DROP PACKAGE
|
||||
CALL db1.pkg1.p1;
|
||||
DROP PACKAGE db1.pkg1;
|
||||
eval $q;
|
||||
|
||||
--echo # DROP DATABASE
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1 AS BEGIN NULL; END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL db1.pkg1.p1;
|
||||
eval $q;
|
||||
DROP DATABASE db1;
|
||||
eval $q;
|
||||
|
||||
DROP DATABASE db2;
|
||||
eval $q;
|
||||
SET sql_mode= @save_sql_mode;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -246,6 +246,8 @@ search:
|
||||
pfs->m_schema_name_length= schema_name_length;
|
||||
pfs->m_enabled= is_enabled;
|
||||
pfs->m_timed= is_timed;
|
||||
pfs->m_stmt_stat.reset();
|
||||
pfs->m_sp_stat.reset();
|
||||
|
||||
/* Insert this record. */
|
||||
pfs->m_lock.dirty_to_allocated(& dirty_state);
|
||||
@@ -277,6 +279,51 @@ search:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Drops records of the routines of a package body.
|
||||
They are named "<package>.<routine>" in the package schema.
|
||||
Names are compared in the lower-cased form of PFS_program_key.
|
||||
*/
|
||||
class Proc_drop_package_routines
|
||||
: public PFS_buffer_processor<PFS_program>
|
||||
{
|
||||
public:
|
||||
Proc_drop_package_routines(LF_PINS *pins,
|
||||
const char *name, uint name_length,
|
||||
const char *schema, uint schema_length)
|
||||
: m_pins(pins), m_name(name), m_name_length(name_length),
|
||||
m_schema(schema), m_schema_length(schema_length)
|
||||
{}
|
||||
|
||||
void operator()(PFS_program *pfs) override
|
||||
{
|
||||
if ((pfs->m_type != OBJECT_TYPE_PROCEDURE &&
|
||||
pfs->m_type != OBJECT_TYPE_FUNCTION) ||
|
||||
uint(pfs->m_object_name_length) <= m_name_length ||
|
||||
pfs->m_object_name[m_name_length] != '.' ||
|
||||
memcmp(pfs->m_object_name, m_name, m_name_length) ||
|
||||
uint(pfs->m_schema_name_length) != m_schema_length ||
|
||||
memcmp(pfs->m_schema_name, m_schema, m_schema_length))
|
||||
return;
|
||||
|
||||
/*
|
||||
Not in the hash yet means find_or_create_program() still owns it.
|
||||
Concurrent creation of the same key is not possible: routines of
|
||||
the package are loaded under MDL of the package body.
|
||||
*/
|
||||
if (!lf_hash_delete(&program_hash, m_pins,
|
||||
pfs->m_key.m_hash_key, pfs->m_key.m_key_length))
|
||||
global_program_container.deallocate(pfs);
|
||||
}
|
||||
|
||||
private:
|
||||
LF_PINS *m_pins;
|
||||
const char *m_name;
|
||||
uint m_name_length;
|
||||
const char *m_schema;
|
||||
uint m_schema_length;
|
||||
};
|
||||
|
||||
void drop_program(PFS_thread *thread,
|
||||
enum_object_type object_type,
|
||||
const char *object_name,
|
||||
@@ -310,7 +357,15 @@ void drop_program(PFS_thread *thread,
|
||||
}
|
||||
|
||||
lf_hash_search_unpin(pins);
|
||||
return;
|
||||
|
||||
if (object_type == OBJECT_TYPE_PACKAGE_BODY)
|
||||
{
|
||||
const char *name= key.m_hash_key + 1;
|
||||
Proc_drop_package_routines proc(pins, name, object_name_length,
|
||||
name + object_name_length + 1,
|
||||
schema_name_length);
|
||||
global_program_container.apply(proc);
|
||||
}
|
||||
}
|
||||
|
||||
void PFS_program::refresh_setup_object_flags(PFS_thread *thread)
|
||||
|
||||
Reference in New Issue
Block a user