- mysql> show status like 'table%';
- +-----------------------+-------+
- | Variable_name | Value |
- +-----------------------+-------+
- | Table_locks_immediate | 2979 |
- | Table_locks_waited | 0 |
- +-----------------------+-------+
- 2 rows in set (0.00 sec))
复制代码
请求锁模式
是否兼容
当前锁模式
|
None
|
读锁
|
写锁
|
读锁
|
是
|
是
|
否
|
写锁
|
是
|
否
|
否
|
读和写操作;MyISAM表的读操作与写操作之间,以及写操作之间是串行的!根据如表20-2所示的例子可以知道,当一个线程获得对一个表的写锁后,只有
持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。
session_1
|
session_2
|
获得表film_text的WRITE锁定
mysql> lock table film_text write;
Query OK, 0 rows affected (0.00 sec)
|
|
当前session对锁定表的查询、更新、插入操作都可以执行:
mysql> select film_id,title from film_text where film_id = 1001;
+---------+-------------+
| film_id | title |
+---------+-------------+
| 1001 | Update Test |
+---------+-------------+
1 row in set (0.00 sec)
mysql> insert into film_text (film_id,title) values(1003,'Test');
Query OK, 1 row affected (0.00 sec)
mysql> update film_text set title = 'Test' where film_id = 1001;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
|
其他session对锁定表的查询被阻塞,需要等待锁被释放:
mysql> select film_id,title from film_text where film_id = 1001;
等待
|
释放锁:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
|
等待
|
Session2获得锁,查询返回:
mysql> select film_id,title from film_text where film_id = 1001;
+---------+-------+
| film_id | title |
+---------+-------+
| 1001 | Test |
+---------+-------+
1 row in set (57.59 sec)
|
DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK
TABLE命令给MyISAM表显式加锁。在本书的示例中,显式加锁基本上都是为了方便而已,并非必须如此。
订单表orders,其中记录有各订单的总金额total,同时还有一个订单明细表order_detail,其中记录有各订单每一产品的金额小计
subtotal,假设我们需要检查这两个表的金额合计是否相符,可能就需要执行如下两条SQL:
- Select sum(total) from orders;
- Select sum(subtotal) from order_detail;
复制代码
- Lock tables orders read local, order_detail read local;
- Select sum(total) from orders;
- Select sum(subtotal) from order_detail;
- Unlock tables;
复制代码
- 上面的例子在LOCK TABLES时加了“local”选项,其作用就是在满足MyISAM表并发插入条件的情况下,允许其他用户在表尾并发插入记录,有关MyISAM表的并发插入问题,在后面的章节中还会进一步介绍。
- 在
用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级。也就是说,在执行LOCK
TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。其实,在自动加锁的
情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。
session_1 |
session_2
|
获得表film_text的READ锁定
mysql> lock table film_text read;
Query OK, 0 rows affected (0.00 sec)
|
|
当前session可以查询该表记录
mysql> select film_id,title from film_text where film_id = 1001;
+---------+------------------+
| film_id | title |
+---------+------------------+
| 1001 | ACADEMY DINOSAUR |
+---------+------------------+
1 row in set (0.00 sec)
|
其他session也可以查询该表的记录
mysql> select film_id,title from film_text where film_id = 1001;
+---------+------------------+
| film_id | title |
+---------+------------------+
| 1001 | ACADEMY DINOSAUR |
+---------+------------------+
1 row in set (0.00 sec)
|
当前session不能查询没有锁定的表
mysql> select film_id,title from film where film_id = 1001;
ERROR 1100 (HY000): Table 'film' was not locked with LOCK TABLES
|
其他session可以查询或者更新未锁定的表
mysql> select film_id,title from film where film_id = 1001;
+---------+---------------+
| film_id | title |
+---------+---------------+
| 1001 | update record |
+---------+---------------+
1 row in set (0.00 sec)
mysql> update film set title = 'Test' where film_id = 1001;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0
|
当前session中插入或者更新锁定的表都会提示错误:
mysql> insert into film_text (film_id,title) values(1002,'Test');
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
mysql> update film_text set title = 'Test' where film_id = 1001;
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
|
其他session更新锁定表会等待获得锁:
mysql> update film_text set title = 'Test' where film_id = 1001;
等待
|
释放锁
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
|
等待
|
Session获得锁,更新操作完成:
mysql> update film_text set title = 'Test' where film_id = 1001;
Query OK, 1 row affected (1 min 0.71 sec)
Rows matched: 1 Changed: 1 Warnings: 0
|
- mysql> lock table actor read;
- Query OK, 0 rows affected (0.00 sec)
复制代码
- mysql> select
a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b
where a.first_name = b.first_name and a.first_name = 'Lisa' and
a.last_name = 'Tom' and a.last_name <> b.last_name; - ERROR 1100 (HY000): Table 'a' was not locked with LOCK TABLES
复制代码
- mysql> lock table actor as a read,actor as b read;
- Query OK, 0 rows affected (0.00 sec)
复制代码
- mysql> select
a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b
where a.first_name = b.first_name and a.first_name = 'Lisa' and
a.last_name = 'Tom' and a.last_name <> b.last_name; - +------------+-----------+------------+-----------+
- | first_name | last_name | first_name | last_name |
- +------------+-----------+------------+-----------+
- | Lisa | Tom | LISA | MONROE |
- +------------+-----------+------------+-----------+
- 1 row in set (0.00 sec)
复制代码
并发插入(Concurrent Inserts)
- 当concurrent_insert设置为0时,不允许并发插入。
- 当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。
- 当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。
LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他的线程(session_2),虽然不能对表进行删除和更新操作,但却可以对该
表进行并发插入操作,这里假设该表中间不存在空洞。
session_1
|
session_2
|
获得表film_text的READ LOCAL锁定
mysql> lock table film_text read local;
Query OK, 0 rows affected (0.00 sec)
|
|
当前session不能对锁定表进行更新或者插入操作:
mysql> insert into film_text (film_id,title) values(1002,'Test');
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
mysql> update film_text set title = 'Test' where film_id = 1001;
ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated
|
其他session可以进行插入操作,但是更新会等待:
mysql> insert into film_text (film_id,title) values(1002,'Test');
Query OK, 1 row affected (0.00 sec)
mysql> update film_text set title = 'Update Test' where film_id = 1001;
等待
|
当前session不能访问其他session插入的记录:
mysql> select film_id,title from film_text where film_id = 1002;
Empty set (0.00 sec)
|
|
释放锁:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
|
等待
|
当前session解锁后可以获得其他session插入的记录:
mysql> select film_id,title from film_text where film_id = 1002;
+---------+-------+
| film_id | title |
+---------+-------+
| 1002 | Test |
+---------+-------+
1 row in set (0.00 sec)
|
Session2获得锁,更新操作完成:
mysql> update film_text set title = 'Update Test' where film_id = 1001;
Query OK, 1 row affected (1 min 17.75 sec)
Rows matched: 1 Changed: 1 Warnings: 0
|
concurrent_insert系统变量设为2,总是允许并发插入;同时,通过定期在系统空闲时段执行OPTIMIZE
TABLE语句来整理空间碎片,收回因删除记录而产生的中间空洞。有关OPTIMIZE
TABLE语句的详细介绍,可以参见第18章中“两个简单实用的优化方法”一节的内容。
读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得锁。不仅如此,即使读请求先到锁等待队列,写请求后到,写锁也会插到
读锁请求之前!这是因为MySQL认为写请求一般比读请求要重要。这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更
新操作会造成查询操作很难获得读锁,从而可能永远阻塞。这种情况有时可能会变得非常糟糕!幸好我们可以通过一些设置来调节MyISAM的调度行为。
- 通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
- 通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
- 通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。
面已经讨论了写优先调度机制带来的问题和解决办法。这里还要强调一点:一些需要长时间运行的查询操作,也会使写进程“饿死”!因此,应用中应尽量避免出现
长时间运行的查询操作,不要总想用一条SELECT语句来解决问题,因为这种看似巧妙的SQL语句,往往比较复杂,执行时间较长,在可能的情况下可以通过
使用中间表等措施对SQL语句做一定的“分解”,使每一步查询都能在较短时间完成,从而减少锁冲突。如果复杂查询不可避免,应尽量安排在数据库空闲时段执
行,比如一些定期统计可以安排在夜间执行。
MyISAM表锁的更多相关文章
-
锁(MySQL篇)—之MyISAM表锁
前言 锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是 ...
-
MySQL- 锁机制及MyISAM表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许 多用户 共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
-
(6)MySQL进阶篇SQL优化(MyISAM表锁)
1.MySQL锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源 (如 CPU.RAM.I/O 等)的抢占以外,数据也是一种供许多用户共享的资源.如何保证数 据并 ...
-
MYSQL进阶学习笔记八:MySQL MyISAM的表锁!(视频序号:进阶_18-20)
知识点九:MySQL MyISAM表锁(共享读锁)(18) 为什么会有锁: 打个比方,我们到淘宝买一件商品,商品只有一件库存,这时候如果还有另外一个人也在买,那么如何解决是你买到还是另一个人买到的问题 ...
-
MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
转载. https://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...
-
MySQL锁(行锁、表锁、页锁、乐观锁、悲观锁等)
锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...
-
MySQL表锁和行锁
锁粒度 MySQL 不同的存储引擎支持不同的锁机制,所有的存储引擎都以自己的方式显现了锁机制,服务器层完全不了解存储引擎中的锁实现: InnoDB 存储引擎既支持行级锁(row-level locki ...
-
MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
原文地址:http://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...
-
MySQL锁(表锁,行锁,共享锁,排它锁,间隙锁)使用详解
锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...
随机推荐
-
NSDICTIONARY获取内容的CRASH
NSString *path = [self.dataPath stringByAppendingPathComponent:@"dummy.plist"]; NSMutableD ...
-
40 个重要的 HTML5 面试问题及答案
本文将列出40个重要的HTML 5面试问题及答案,祝各位求职顺利. 目录 介绍 Canvas和SVG图形之间的区别是什么? 如何使用Canvas和SVG绘制矩形? 什么是CSS选择器? 如何使用ID值 ...
-
asp.net MVC Razor 语法(1)
Razor 不是编程语言.它是服务器端标记语言. 什么是 Razor ? Razor 是一种允许您向网页中嵌入基于服务器的代码(Visual Basic 和 C#)的标记语法. 当网页被写入浏览器时, ...
-
java-成员方法/变量、类方法/变量等区别
方法 成员方法 成员方法也叫实例方法.必须先有实例即对象,然后才能通过实例调用该实例方法. 类方法 和类变量一样,有关键字static修饰,可以不用实例,直接用类就可以调用类方法. 变量 成员变量 也 ...
-
软件测试3gkd
一.单元测试的任务 单元测试主要是对软件的基本组成单元进行测试,且所测试单元与程序的其他部分在测试中相隔离. 在单元测试中,我们需要对与程序构建中的单位测试以保证其可靠运行与代码规范. 单元测 ...
-
定位公网丢包的工具 mtr
1.使用mtr工具,可以显示从本机到目的ip之间的沿途路由器,从而可以确定丢包的位置. 2.windows 系统,可以使用winmtr工具.
-
( 转) Awesome Image Captioning
Awesome Image Captioning 2018-12-03 19:19:56 From: https://github.com/zhjohnchan/awesome-image-capti ...
-
将 Ubuntu 16.04 LTS 升级到 Ubuntu 18.04 LTS
将 Ubuntu 16.04 LTS 升级到 Ubuntu 18.04 LTS Ubuntu 18.04 LTS(Bionic Beaver)即将发布, 如果您正在使用Ubuntu 16.04LT ...
-
java时间操作:获取当天剩余时间
mport org.apache.commons.lang.time.DateUtils; import org.joda.time.DateTime; import org.joda.time.Du ...
-
监控mysql状态并发送Email
*/10 * * * * /shell/mysql_status.sh > /dev/null 2>&1 #!/bin/bash port55=`/usr/sbin/lsof - ...