mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-10569: Add RELEASE_ALL_LOCKS function. Implementing the SQL
function to release all named locks
This commit is contained in:
committed by
Sergey Vojtovich
parent
98adcffe46
commit
127fee998f
@ -1641,3 +1641,94 @@ DROP TABLE t1;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
#
|
||||
# MDEV-10569 Add RELEASE_ALL_LOCKS SQL-function
|
||||
#
|
||||
# Test function without any locks
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
RELEASE_ALL_LOCKS()
|
||||
0
|
||||
# Test function with one lock only
|
||||
SELECT GET_LOCK('l1',10);
|
||||
GET_LOCK('l1',10)
|
||||
1
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
RELEASE_ALL_LOCKS()
|
||||
1
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA
|
||||
# Test function with multiple locks
|
||||
SELECT GET_LOCK('l01',10),
|
||||
GET_LOCK('l02',10),
|
||||
GET_LOCK('l03',10),
|
||||
GET_LOCK('l04',10),
|
||||
GET_LOCK('l05',10),
|
||||
GET_LOCK('l06',10),
|
||||
GET_LOCK('l07',10),
|
||||
GET_LOCK('l08',10),
|
||||
GET_LOCK('l09',10),
|
||||
GET_LOCK('l10',10),
|
||||
GET_LOCK('l11',10),
|
||||
GET_LOCK('l12',10),
|
||||
GET_LOCK('l13',10),
|
||||
GET_LOCK('l14',10),
|
||||
GET_LOCK('l15',10);
|
||||
GET_LOCK('l01',10) GET_LOCK('l02',10) GET_LOCK('l03',10) GET_LOCK('l04',10) GET_LOCK('l05',10) GET_LOCK('l06',10) GET_LOCK('l07',10) GET_LOCK('l08',10) GET_LOCK('l09',10) GET_LOCK('l10',10) GET_LOCK('l11',10) GET_LOCK('l12',10) GET_LOCK('l13',10) GET_LOCK('l14',10) GET_LOCK('l15',10)
|
||||
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA
|
||||
MDL_SHARED_NO_WRITE User lock l01
|
||||
MDL_SHARED_NO_WRITE User lock l02
|
||||
MDL_SHARED_NO_WRITE User lock l03
|
||||
MDL_SHARED_NO_WRITE User lock l04
|
||||
MDL_SHARED_NO_WRITE User lock l05
|
||||
MDL_SHARED_NO_WRITE User lock l06
|
||||
MDL_SHARED_NO_WRITE User lock l07
|
||||
MDL_SHARED_NO_WRITE User lock l08
|
||||
MDL_SHARED_NO_WRITE User lock l09
|
||||
MDL_SHARED_NO_WRITE User lock l10
|
||||
MDL_SHARED_NO_WRITE User lock l11
|
||||
MDL_SHARED_NO_WRITE User lock l12
|
||||
MDL_SHARED_NO_WRITE User lock l13
|
||||
MDL_SHARED_NO_WRITE User lock l14
|
||||
MDL_SHARED_NO_WRITE User lock l15
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
RELEASE_ALL_LOCKS()
|
||||
15
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA
|
||||
# Test function with recursive locks
|
||||
SELECT GET_LOCK('l1',10),
|
||||
GET_LOCK('l2',10),
|
||||
GET_LOCK('l2',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10);
|
||||
GET_LOCK('l1',10) GET_LOCK('l2',10) GET_LOCK('l2',10) GET_LOCK('l3',10) GET_LOCK('l3',10) GET_LOCK('l3',10) GET_LOCK('l4',10) GET_LOCK('l4',10) GET_LOCK('l4',10) GET_LOCK('l4',10) GET_LOCK('l5',10) GET_LOCK('l5',10) GET_LOCK('l5',10) GET_LOCK('l5',10) GET_LOCK('l5',10)
|
||||
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA
|
||||
MDL_SHARED_NO_WRITE User lock l1
|
||||
MDL_SHARED_NO_WRITE User lock l2
|
||||
MDL_SHARED_NO_WRITE User lock l3
|
||||
MDL_SHARED_NO_WRITE User lock l4
|
||||
MDL_SHARED_NO_WRITE User lock l5
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
RELEASE_ALL_LOCKS()
|
||||
15
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
LOCK_MODE LOCK_TYPE TABLE_SCHEMA
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Testing of misc functions
|
||||
#
|
||||
|
||||
--source include/have_metadata_lock_info.inc
|
||||
--source include/default_optimizer_switch.inc
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
@ -1278,3 +1278,60 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-10569 Add RELEASE_ALL_LOCKS SQL-function
|
||||
--echo #
|
||||
|
||||
--echo # Test function without any locks
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
|
||||
--echo # Test function with one lock only
|
||||
SELECT GET_LOCK('l1',10);
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
|
||||
--echo # Test function with multiple locks
|
||||
SELECT GET_LOCK('l01',10),
|
||||
GET_LOCK('l02',10),
|
||||
GET_LOCK('l03',10),
|
||||
GET_LOCK('l04',10),
|
||||
GET_LOCK('l05',10),
|
||||
GET_LOCK('l06',10),
|
||||
GET_LOCK('l07',10),
|
||||
GET_LOCK('l08',10),
|
||||
GET_LOCK('l09',10),
|
||||
GET_LOCK('l10',10),
|
||||
GET_LOCK('l11',10),
|
||||
GET_LOCK('l12',10),
|
||||
GET_LOCK('l13',10),
|
||||
GET_LOCK('l14',10),
|
||||
GET_LOCK('l15',10);
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
|
||||
--echo # Test function with recursive locks
|
||||
SELECT GET_LOCK('l1',10),
|
||||
GET_LOCK('l2',10),
|
||||
GET_LOCK('l2',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l3',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l4',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10),
|
||||
GET_LOCK('l5',10);
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
||||
SELECT RELEASE_ALL_LOCKS();
|
||||
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA
|
||||
FROM information_schema.metadata_lock_info WHERE thread_id>0 ORDER BY TABLE_SCHEMA;
|
@ -1765,6 +1765,15 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class Create_func_release_all_locks : public Create_func_arg0
|
||||
{
|
||||
public:
|
||||
virtual Item *create_builder(THD *thd);
|
||||
|
||||
static Create_func_release_all_locks s_singleton;
|
||||
};
|
||||
|
||||
|
||||
class Create_func_release_lock : public Create_func_arg1
|
||||
{
|
||||
public:
|
||||
@ -4762,6 +4771,17 @@ Create_func_rand::create_native(THD *thd, LEX_CSTRING *name,
|
||||
}
|
||||
|
||||
|
||||
Create_func_release_all_locks Create_func_release_all_locks::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_release_all_locks::create_builder(THD *thd)
|
||||
{
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
return new (thd->mem_root) Item_func_release_all_locks(thd);
|
||||
}
|
||||
|
||||
|
||||
Create_func_release_lock Create_func_release_lock::s_singleton;
|
||||
|
||||
Item*
|
||||
@ -5525,6 +5545,8 @@ static Native_func_registry func_array[] =
|
||||
{ { STRING_WITH_LEN("REGEXP_SUBSTR") }, BUILDER(Create_func_regexp_substr)},
|
||||
{ { STRING_WITH_LEN("RADIANS") }, BUILDER(Create_func_radians)},
|
||||
{ { STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
|
||||
{ { STRING_WITH_LEN("RELEASE_ALL_LOCKS") },
|
||||
BUILDER(Create_func_release_all_locks)},
|
||||
{ { STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
|
||||
{ { STRING_WITH_LEN("REPLACE_ORACLE") },
|
||||
BUILDER(Create_func_replace_oracle)},
|
||||
|
@ -4028,7 +4028,7 @@ longlong Item_func_get_lock::val_int()
|
||||
MDL_request ull_request;
|
||||
ull_request.init(MDL_key::USER_LOCK, res->c_ptr_safe(), "",
|
||||
MDL_SHARED_NO_WRITE, MDL_EXPLICIT);
|
||||
MDL_key *ull_key = &ull_request.key;
|
||||
MDL_key *ull_key= &ull_request.key;
|
||||
|
||||
|
||||
if ((ull= (User_level_lock*)
|
||||
@ -4036,7 +4036,7 @@ longlong Item_func_get_lock::val_int()
|
||||
{
|
||||
/* Recursive lock */
|
||||
ull->refs++;
|
||||
null_value = 0;
|
||||
null_value= 0;
|
||||
DBUG_PRINT("info", ("recursive lock, ref-count: %d", (int) ull->refs));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -4075,6 +4075,30 @@ longlong Item_func_get_lock::val_int()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Release all user level locks.
|
||||
@return
|
||||
- N if N-lock released
|
||||
- 0 if lock wasn't held
|
||||
*/
|
||||
longlong Item_func_release_all_locks::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
THD *thd= current_thd;
|
||||
ulong num_unlocked= 0;
|
||||
DBUG_ENTER("Item_func_release_all_locks::val_int");
|
||||
for (size_t i= 0; i < thd->ull_hash.records; i++)
|
||||
{
|
||||
auto ull= (User_level_lock *) my_hash_element(&thd->ull_hash, i);
|
||||
thd->mdl_context.release_lock(ull->lock);
|
||||
num_unlocked+= ull->refs;
|
||||
my_free(ull);
|
||||
}
|
||||
my_hash_free(&thd->ull_hash);
|
||||
DBUG_RETURN(num_unlocked);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Release a user level lock.
|
||||
@return
|
||||
|
@ -2654,7 +2654,27 @@ public:
|
||||
void mysql_ull_cleanup(THD *thd);
|
||||
void mysql_ull_set_explicit_lock_duration(THD *thd);
|
||||
|
||||
class Item_func_get_lock :public Item_long_func
|
||||
|
||||
class Item_func_lock :public Item_long_func
|
||||
{
|
||||
public:
|
||||
Item_func_lock(THD *thd): Item_long_func(thd) { }
|
||||
Item_func_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
|
||||
Item_func_lock(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
|
||||
table_map used_tables() const
|
||||
{
|
||||
return used_tables_cache | RAND_TABLE_BIT;
|
||||
}
|
||||
bool const_item() const { return 0; }
|
||||
bool is_expensive() { return 1; }
|
||||
bool check_vcol_func_processor(void *arg)
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Item_func_get_lock final :public Item_func_lock
|
||||
{
|
||||
bool check_arguments() const
|
||||
{
|
||||
@ -2663,48 +2683,42 @@ class Item_func_get_lock :public Item_long_func
|
||||
}
|
||||
String value;
|
||||
public:
|
||||
Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "get_lock"; }
|
||||
bool fix_length_and_dec() { max_length=1; maybe_null=1; return FALSE; }
|
||||
table_map used_tables() const
|
||||
{
|
||||
return used_tables_cache | RAND_TABLE_BIT;
|
||||
}
|
||||
bool const_item() const { return 0; }
|
||||
bool is_expensive() { return 1; }
|
||||
bool check_vcol_func_processor(void *arg)
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
|
||||
}
|
||||
Item *get_copy(THD *thd)
|
||||
Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_func_lock(thd, a, b) {}
|
||||
longlong val_int() final;
|
||||
const char *func_name() const final { return "get_lock"; }
|
||||
bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
|
||||
Item *get_copy(THD *thd) final
|
||||
{ return get_item_copy<Item_func_get_lock>(thd, this); }
|
||||
};
|
||||
|
||||
class Item_func_release_lock :public Item_long_func
|
||||
|
||||
class Item_func_release_all_locks final :public Item_func_lock
|
||||
{
|
||||
public:
|
||||
Item_func_release_all_locks(THD *thd): Item_func_lock(thd)
|
||||
{ unsigned_flag= 1; }
|
||||
longlong val_int() final;
|
||||
const char *func_name() const final { return "release_all_locks"; }
|
||||
Item *get_copy(THD *thd) final
|
||||
{ return get_item_copy<Item_func_release_all_locks>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_release_lock final :public Item_func_lock
|
||||
{
|
||||
bool check_arguments() const
|
||||
{ return args[0]->check_type_general_purpose_string(func_name()); }
|
||||
String value;
|
||||
public:
|
||||
Item_func_release_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
|
||||
longlong val_int();
|
||||
Item_func_release_lock(THD *thd, Item *a): Item_func_lock(thd, a) {}
|
||||
longlong val_int() final;
|
||||
const char *func_name() const { return "release_lock"; }
|
||||
bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
|
||||
table_map used_tables() const
|
||||
{
|
||||
return used_tables_cache | RAND_TABLE_BIT;
|
||||
}
|
||||
bool const_item() const { return 0; }
|
||||
bool is_expensive() { return 1; }
|
||||
bool check_vcol_func_processor(void *arg)
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
|
||||
}
|
||||
Item *get_copy(THD *thd)
|
||||
Item *get_copy(THD *thd) final
|
||||
{ return get_item_copy<Item_func_release_lock>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
/* replication functions */
|
||||
|
||||
class Item_master_pos_wait :public Item_longlong_func
|
||||
|
Reference in New Issue
Block a user