3 锁
MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行页级锁定,对InnoDB表进行行级锁定。
MySQL中用于 WRITE(写) 的表锁的实现机制如下:如果表没有加锁,那么就加一个写锁。 否则的话,将请求放到写锁队列中。
MySQL中用于 READ(读) 的表锁的实现机制如下:如果表没有加写锁,那么就加一个读锁。 否则的话,将请求放到读锁队列中。
当锁释放后,写锁队列中的线程可以用这个锁资源,然后才轮到读锁队列中的线程。这就是说,如果表里有很多更新操作的话,那么 SELECT 必须等到所有的更新都完成了之后才能开始。从 MySQL 3.23.33 开始,可以通过状态变量 Table_locks_waited 和 Table_locks_immediate 来分析系统中的锁表争夺情况:
mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 3008994 |
| Table_locks_waited | 0 |
+-----------------------+---------+
2 rows in set (1.36 sec)
我还是习惯用共享锁和独占锁的概念:
共享锁S:事务获得共享锁允许读取一条记录。
独占锁X: 事务获得独占锁允许更新或者删除一条记录。
如果事务T1在表t上获得了一个共享锁:事务T2也可以在表t上获得一个共享锁,两个事务可以同时在表t上获得共享锁;事务T2如果想在表t上获得一个独占锁,将不能立即获得。
如果事务T1在表t上获得一个独占锁:其实事务不能在表t上获得任何类型的锁。
InnoDB支持多粒度锁,行锁和表锁,和ORACLE类似,MYSQL也有意向锁的概念:
意向共享锁和意向排它锁。我们介绍一下意向锁的概念:
表是由行组成的,当我们向某个表加锁时,一方面需要检查该锁的申请是否与原有的表级锁相容;另一方面,还要检查该锁是否与表中的每一行上的锁相容。比如一个事务要在一个表上加S锁,如果表中的一行已被另外的事务加了X锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,可以在表级引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。
意向锁的含义是如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对它的上层结点加意向锁。
如:对表中的任一行加锁时,必须先对它所在的表加意向锁,然后再对该行加锁。这样一来,事务对表加锁时,就不再需要检查表中每行记录的锁标志位了,系统效率得以大大提高。
由此我们可以看出MYSQL中的两种意向锁:意向共享锁和意向排它锁。
几种类型锁定的兼容性:

LOCK TABLE示例:
SESSION 1:
mysql> lock tables t write;
Query OK, 0 rows affected (0.02 sec)
SESSION 2:
mysql> select * from t;
SESSION 1:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
SESSION 2:
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 33 |
+------+
3 rows in set (59.28 sec)