锁是计算机协调多个进程或线程并发访问某一资源的机制,相对其他数据库而言,Mysql的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如Myisam和Memory存储引擎采用的是表级锁;BDB存储引擎采用的是页面锁,但也支持表级锁;Innodb存储引擎既支持行级锁也支持表级锁;以下是他们各自锁的区别:

    表级锁:开销小,加锁快;不会出现死锁;锁粒度大.发生锁冲突概率最高,并发度最低.

    行级锁:开销大,加锁慢;会出现死锁,锁粒度最小;发生锁冲突概率最高,并发度也最高.

    页面锁:开销和加锁时间界于表锁和行锁之间,会出现死锁;锁粒度界于表锁和行锁之间.

1.Myisam 锁问题:

    查询表级锁争用情况:

       table_locks_waited       table_locks_immediate  

       如果值较高,说明存在着严重的争锁情况.

    表级锁的锁模式: 共享锁和排他锁.两锁之间是冲突的,知道锁线程释放.

    在执行select前会自动为表加锁,使表具备只读,执行update/insert/delete 会自动为表加排他锁;

     mysql不支持锁升级,也就是说显示加锁后,只允许访问加锁的表,隐式加锁也一样.

     并发插入:在一定条件下.mysql支持查询与插入一同操作.

    允许并发插入相关参数设置:concurrent_insert = 0/1/2

     0:不允许并发插入.

     1:当有记录从该表删除时,表中有空洞才允许并发插入.

     2:不管有无空洞,都允许并发插入.

     查看表是否有空洞:show table status like 'table_name';

     Data_free:      这一项则表示delete删除记录后是否有空隙.

    Myisam的锁调度:

    默认情况下,写进程优先获得锁.即使读请求在写请求队列前,写请求也会优先获得锁.

2:Innodb锁问题:

    事务的ACID属性:

  A:原子性,指事务是一个原子操作单元,其对数据的修改,要么全部执行成功,要么全部不执行.

  C:一致性,在事务开始和结束时.数据都必须保持一致状态,这意味着所有数据规则都必须应用于事务的修改,以保证事务的完整性.事务结束时,所有内部数据(如:索引)都必须正确.

  I:隔离性,提供一定的隔离机制,保证事务在不受外部并发操作影响的"独立"环境下执行,事务与事务之间是不可见的.

  D:持久性,事务完成之后,它对事务的修改是永久性的.即使出现系统的故障也能保持.

相关事务的例子:可以想象一下银行转账.

  获取Innodb行锁争用情况:

   innodb_row_lock_waits      innodb_row_lock_time_avg   

   Innodb 是通过给索引的索引项加锁来实现的.这意味着Innodb只使用索引来检索数据才会使用行锁,否则使用表锁.

  大家又可以想象,因为Innodb是为索引加锁,所以如果两个事务使用同一个索引的话,已然会出现锁等待问题.

   即使条件中使用了索引,但mysql的执行计划认为全表扫描的效率高,则会放弃使用索引,所以在分析锁冲突时不要忘记分析sql计划.

   Explain Query; 我们也可以强制mysql使用索引 force index 'index_name'.

  间隙锁:

  为范围的条件值加锁,尽管条件并不存在,避免产生幻读.

例: select * form table_name where id > 100;

那么Innodb会为大于100的索引项加锁,尽管没有101,102....

  尽管请求一个不存在的记录时,Innodb也会为这个不存在的值索引加锁.

  在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录,也就是不允许出现幻读.