加入收藏 | 设为首页 | 会员中心 | 我要投稿 汽车网 (https://www.0577qiche.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

如何处理锁的竞争问题

发布时间:2023-09-06 13:07:44 所属栏目:MySql教程 来源:
导读:使用锁来控制资源共享的应用系统,如何处理锁的竞争问题是个头疼事。MysqL 有两个级别的锁等待,服务器级别和存储引擎级别,本节重点介绍服务器级别的锁等待。

1. 表锁
表锁可以是显式的,也可以是隐式的。

1
使用锁来控制资源共享的应用系统,如何处理锁的竞争问题是个头疼事。MysqL 有两个级别的锁等待,服务器级别和存储引擎级别,本节重点介绍服务器级别的锁等待。

1. 表锁
表锁可以是显式的,也可以是隐式的。

1.1 显式锁
通过 lock tables和unlock tables 可以控制显式锁。在 MysqL 会话中执行 lock tables 命令,在表customer上会获得一个显式锁。

MysqL> lock tables customer read;
Query OK,  rows affected ( sec)
在 MysqL 另一个会话中,对表 customer 执行 lock tables 命令,查询会挂起。

MysqL> lock tables customer write;
在第一个会话中执行 show processlist 查看线程状态,可以看到线程 13239868 的状态为 Waiting for table Metadata lock。在 MysqL 中,当一个线程持有该锁后,其他线程只能不断尝试获取。

MysqL> show processlist\G
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: starting
   Info: show processlist
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: Waiting for table Metadata lock
   Info: lock tables customer write
 rows in set ( sec)
 
1.2 隐式锁
除了显式锁会阻塞这样的操作,MysqL 在查询过程中也会隐式地锁住表。通过 sleep() 函数可以实现长时间的查询,然后 MysqL 会产生一个隐式锁。

在 MysqL 会话中执行 sleep(30),在表 customer上 会获得一个隐式锁。

MysqL> select sleep() from customer;
在 MysqL 另一个会话中,对表 customer 执行 lock tables 命令,查询会挂起。

MysqL> lock tables customer write;
在第三个会话中执行 show processlist 查看线程状态,可以看到线程 13244135 的状态为 Waiting for table Metadata lock。select 查询的隐式锁阻塞了 lock tables 中所请求的显式写锁。

MysqL> show processlist\G
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: User sleep
   Info: select sleep() from customer
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: Waiting for table Metadata lock
   Info: lock tables customer write
   
2. 全局锁
MysqL 服务器可以支持全局读锁,可以通过 flush tables with read lock 或设置 read_only=1 来实现,全局锁与任何表锁都冲突。

在 MysqL会 话中执行 flush tables 命令,获得全局读锁。

MysqL> flush tables with read lock;
Query OK,  rows affected ( sec)
在 MysqL 另一个会话中,对表 customer 执行 lock tables 命令,查询会挂起。

MysqL> lock tables customer write;
在第一个会话中执行 show processlist 查看线程状态,可以看到线程 13283816 的状态为 Waiting for global read lock。这是一个全局读锁,而不是表级别锁。

MysqL> show processlist\G
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: starting
   Info: show processlist
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: Waiting for global read lock
   Info: lock tables customer write
 rows in set ( sec)
 
3. 命名锁
命名锁是一种表级别锁,它是 MysqL 服务器在重命名或删除表时创建。命名锁与普通的表锁冲突,无论是显式的还是隐式的表锁。

在 MysqL会 话中执行 lock table s命令,在表 customer上 获得一个显式锁。

MysqL> lock tables customer read;
Query OK,  rows affected ( sec)
在 MysqL 另一个会话中,对表 customer 执行 rename table 命令,此时会话会挂起,会话状态为Waiting for table Metadata lock:

MysqL> rename table customer to customer_1;
MysqL> show processlist\G
...
*************************** . row ***************************
     Id: 
   User: root
   Host: localhost
     : tempdb
Command: Query
   Time: 
  State: Waiting for table Metadata lock
   Info: rename table customer to customer_1

4. 小结
本小节介绍了服务器级别的锁等待:表锁、全局锁、命名锁。

表锁可以是显式的,也可以是隐式的。显式锁通过 lock tables 和 unlock tables 进行控制,隐式锁在查询过程中产生。全局锁可以通过 flush tables with read lock 或设置 read_only=1 来 实现,它与任何表锁都冲突。

 

(编辑:汽车网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章