1、上面的例子在LOCK TABLES时加了“local”选项,其作用就是在满足MyISAM表并发插入条件的情况下,允许其他用户在表尾并发插入记录,有关MyISAM表的并发插入问题,在后面还会进一步介绍 。
2、在用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级 。也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作 。其实,在自动加锁的 情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁 。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因 。
当使用LOCK TABLES时,不仅需要一次锁定用到的所有表,而且,同一个表在SQL语句中出现多少次,就要通过与SQL语句中相同的别名锁定多少次,否则也会出错!举例说明如下 。
(1)对actor表获得读锁:
> mysql> lock table actor read; > Query OK, 0 rows affected (0.00 sec)
(2)但是通过别名访问会提示错误:
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 (3)需要对别名分别锁定:
mysql> lock table actor as a read,actor as b read;Query OK, 0 rows affected (0.00 sec)
(4)按照别名的查询可以正确执行:
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)
查询表级锁争用情况
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
mysql> show status like 'table%';Variable_name | Value Table_locks_immediate | 2979 Table_locks_waited | 0 2 rows in set (0.00 sec))
如果Table_locks_waited的值比较高,则说明存在着较严重的表级锁争用情况 。
并发插入(Concurrent Inserts)
上文提到过MyISAM表的读和写是串行的,但这是就总体而言的 。在一定条件下,MyISAM表也支持查询和插入操作的并发进行 。
MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2 。
- 当concurrent_insert设置为0时,不允许并发插入 。
- 当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录 。这也是MySQL的默认设置 。
- 当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录 。
在下面的例子中,session_1获得了一个表的READ LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他的线程(session_2),虽然不能对表进行删除和更新操作,但却可以对该表进行并发插入操作,这里假设该表中间不存在空洞 。
MyISAM存储引擎的读写(INSERT)并发例子:
文章插图
可以利用MyISAM存储引擎的并发插入特性,来解决应 用中对同一表查询和插入的锁争用 。例如,将concurrent_insert系统变量设为2,总是允许并发插入;同时,通过定期在系统空闲时段执行 OPTIMIZE TABLE语句来整理空间碎片,收回因删除记录而产生的中间空洞 。
MyISAM的锁调度
前面讲过,MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的 。那么,一个进程请求某个 MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得锁 。不仅如此,即使读请求先到锁等待队列,写请求后 到,写锁也会插到读锁请求之前!这是因为MySQL认为写请求一般比读请求要重要 。这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原 因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞 。这种情况有时可能会变得非常糟糕!幸好我们可以通过一些设置来调节MyISAM 的调度行为 。
推荐阅读
- MySQL高级查询
- Swift 中的命令行应用
- M MySQL VARCHAR最多能存储多少数据
- 恋爱中的犀牛 话剧?犀牛的恋爱话剧台词
- yaya|泰星Yaya谈婚期:我已经准备好了,我梦想中的结婚地点是在挪威
- 分手大师|《分手大师》当中的男人梅远贵,拥有一个特殊的职业,让人意外
- 电影|《色·戒》当中的梁朝伟身为男主角,却扮演的是一个反派
- 容祖儿|赵本山戏中的“御用老伴”关婷娜,39岁的她身材丰腴,大秀美腿
- 藏红花油其中的功效和作用是什么?
- 九宫飞星图风水方位详解 九宫飞星图
