MyISAM表锁
1、MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求。
2、MyISAM 表的写操作,会阻塞其他用户对同一表的读和写操作。
3、MySQL 不支持锁升级,也就是说,在执行 LOCK TABLES 后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。
一、MyISAM加表锁
注意:使用 LOCK TABLES 需要一次锁定用到的所有表,而且同一个表在 SQL 语句中出现多次,就要通过与 SQL 语句中相同的别名锁定多少次,否则也会出错。如下所示
1)锁表
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='GG' and a.last_name <> b.last_name;
ERROR 1100 (HY000): Table 'a' was not locked with LOCK TABLES
mysql>
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='GG' and a.last_name <> b.last_name;
+------------+-----------+------------+-----------+
| first_name | last_name | first_name | last_name |
+------------+-----------+------------+-----------+
| LISA | GG | LISA | MONROE |
+------------+-----------+------------+-----------+
1 row in set (0.00 sec)
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
二、MyISAM并发插入(Concurrent Inserts)
#不允许并发插入
concurrent_insert=0
#默认设置,如果 MyISAM 表中没有空洞(表的中间没有被删除的行),MyISAM 允许一个进程读表的同时,另一个进程从表尾插入记录。
concurrent_insert=1
#无论 MyISAM 表中有没有空洞,都允许在表尾并发插入记录。
concurrent_insert=2
备注:可以利用 MyISAM 存储引擎的并发插入特性来解决应用中对同一表查询和插入的锁争用。如,将 concurrent_insert 系统变量设为 2 ,总是允许并发插入;同时,通过定期在系统空闲时段执行 OPTIMIZE TABLE table_name 语句来整理空间碎片,回收因删除记录而产生的中间空洞。
三、MyISAM锁调度
MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的。写进程总是先获得锁,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前,因为MySQL认为 写请求一般比读请求更重要。所以MyISAM表不太适合于有大量更新操作和查询操作应用
###可以通过如下调节MyISAM的调度行为
1)指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
2)执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
3)指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。
4)给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。