一,概述
  相对其他数据库而言,mysql的锁机制比较简单,其显著的特点是不同的存储引擎支持不同的锁机制。比如:myisam和memory存储引擎采用的是表级锁,bdb采用的是页面锁,但也支持表级锁,innodb存储引擎即支持行级锁也支持表级锁,但默认情况下是行级锁。
  三种锁的特性大致归纳如下:
  (1)表级锁:开销小,加锁快;不会出现死锁;锁粒度大,发生冲突的概率高,并发度低。
  (2)行级锁:开销大,加锁慢;会出现锁死;锁粒度小,发生锁冲突的概率低,并发度也高。
  (3)页面锁: 开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。
  所以,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用。而行级锁则更适合于有大量按照索引条件并发更新少量不同数据,同时又有并发查询的应用。
  二,myisam表锁
  1,通过查看状态变量来分析系统上表锁定争夺
  mysql> show status like 'table_lock%';
  +-----------------------+-------+
  | Variable_name         | Value |
  +-----------------------+-------+
  | Table_locks_immediate | 101   |
  | Table_locks_waited    | 0     |
  +-----------------------+-------+
  2 rows in set (0.00 sec)
  以上两个数据,如果table_locks_waited的值更高,则说明存在较严重的表级锁争用情况。
  2,表级锁的锁模式
  mysql的表级锁有两种模式:表共享读锁(table read lock)和表独占写锁(table write lock)。锁模式的兼容性如下:
  mysql表锁兼容性 none 读锁 写锁 读锁 是 是 否 写锁 是 否 否
  可见,对myisam表的读操作不会阻塞其他用户对同一表的读操作,但会阻塞对同一表的写操作.
  对myisam表的写操作则会阻塞其他用户对同一表的读和写操作。
  myisam表的读操作与写操作之间,以及写操作之间是串行的。
  下面我们来看一个例子:
  首先,我们创建表并插入几条数据,看一下表的结构:
  mysql> create table t18(id int auto_increment primary key,name varchar(63),age int(3));
  Query OK, 0 rows affected (0.33 sec)
  mysql> insert into t18(name,age)values('fzy1',1),('fzy2',2),('fzy3',3);
  Query OK, 3 rows affected (0.07 sec)
  Records: 3  Duplicates: 0  Warnings: 0
  mysql> select * from t18;
  +----+------+------+
  | id | name | age  |
  +----+------+------+
  |  1 | fzy1 |    1 |
  |  2 | fzy2 |    2 |
  |  3 | fzy3 |    3 |
  +----+------+------+
  3 rows in set (0.00 sec)
  写阻塞读例子 session_1 session_2 获得表t18的write锁
  mysql> lock table t18 write;
  Query OK, 0 rows affected (0.00 sec)
  当前session对锁定的表的查询,更新,插入操作都可以执行
  mysql> insert into t18(name,age)values('fzy4',4);
  Query OK, 1 row affected (0.04 sec)
  mysql> update t18 set age=5 where id=2;
  Query OK, 1 row affected (0.11 sec)
  Rows matched: 1  Changed: 1  Warnings: 0
  mysql> select * from t18;
  +----+------+------+
  | id | name | age  |
  +----+------+------+
  |  1 | fzy1 |    1 |
  |  2 | fzy2 |    5 |
  |  3 | fzy3 |    3 |
  |  4 | fzy4 |    4 |
  +----+------+------+
  4 rows in set (0.00 sec)
  其他session对锁定的表操作被阻塞
  mysql> select * from t18;
  等待
  释放锁
  mysql> unlock tables;
  Query OK, 0 rows affected (0.00 sec)
  等待 session2获得锁,返回查询结果
  +----+------+------+
  | id | name | age  |
  +----+------+------+
  |  1 | fzy1 |    1 |
  |  2 | fzy2 |    5 |
  |  3 | fzy3 |    3 |
  |  4 | fzy4 |    4 |
  +----+------+------+
  4 rows in set (1 min 21.56 sec)
  读阻塞写例子 session_1 session_2 获得t18的read锁定
  mysql> lock table t18 read;
  Query OK, 0 rows affected (0.00 sec)
  当前session可以查询该表记录
  mysql> select * from t18;
  +----+------+------+
  | id | name | age  |
  +----+------+------+
  |  1 | fzy1 |    1 |
  |  2 | fzy2 |    5 |
  |  3 | fzy3 |    3 |
  |  4 | fzy4 |    4 |
  +----+------+------+
  4 rows in set (0.00 sec)
  session_2也可以获得该表记录
  mysql> select * from t18;
  +----+------+------+
  | id | name | age  |
  +----+------+------+
  |  1 | fzy1 |    1 |
  |  2 | fzy2 |    5 |
  |  3 | fzy3 |    3 |
  |  4 | fzy4 |    4 |
  +----+------+------+
  4 rows in set (0.00 sec)
  当前session不能查询未锁定的表,但可以看锁定的表(这个会话中锁定的表)
  mysql> select * from t17;
  ERROR 1100 (HY000): Table 't17' was not locked with LOCK TABLES
  其他session可以查询和更新未锁定的表
  mysql> select * from t17;
  +----+------+------+--------+
  | id | name | age  | intro  |
  +----+------+------+--------+
  |  1 | fzy1 |    1 | intro1 |
  |  2 | fzy2 |    2 | intro2 |
  |  3 | fzy3 |    3 | intro3 |
  |  4 | hsq  |    4 | intro4 |
  +----+------+------+--------+
  4 rows in set (0.00 sec)
  当前session中插入或更新数据都会报错
  mysql> insert into t18(name,age)values('fzy5',5);
  ERROR 1100 (HY000): Table 't18' was not locked with LOCK TABLES
  其他session更新锁定的表会等待获得锁
  mysql> insert into t18(name,age)values('fzy6',6);
  等待
  释放锁
  mysql> unlock tables;
  Query OK, 0 rows affected (0.00 sec)
  等待 获得锁执行
  Query OK, 1 row affected (2 min 33.25 sec)