如何处理锁的竞争问题
发布时间:2023-09-06 13:07:44 所属栏目:MySql教程 来源:
导读:使用锁来控制资源共享的应用系统,如何处理锁的竞争问题是个头疼事。MysqL 有两个级别的锁等待,服务器级别和存储引擎级别,本节重点介绍服务器级别的锁等待。
1. 表锁
表锁可以是显式的,也可以是隐式的。
1
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 来 实现,它与任何表锁都冲突。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐