锁的分类

  1. 从数据操作的类型(读、写)分
    • 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
      • 当前session不能读其他表,也不能修改
    • 写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。
  2. 从对数据操作的颗粒度
    • 表锁
      • MyIASM存储引擎
      • 开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低
    • 行锁
      • InnoDB存储引擎
      • 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
      • 支持事务
      • 行级锁

表锁

表共享读锁,独占写锁

  1. # 查看当前数据库中表的上锁情况:0 表示未上锁
  2. mysql> show open tables;
  3. +--------------------+----------------------------------------------------+--------+-------------+
  4. | Database | Table | In_use | Name_locked |
  5. +--------------------+----------------------------------------------------+--------+-------------+
  6. | performance_schema | events_waits_history | 0 | 0 |
  7. | performance_schema | events_waits_summary_global_by_event_name | 0 | 0 |
  8. | performance_schema | setup_timers | 0 | 0 |
  9. | performance_schema | events_waits_history_long | 0 | 0 |
  10. | performance_schema | events_statements_summary_by_digest | 0 | 0 |
  11. ....
  12. # 添加锁
  13. lock table 表名1 read(write), 表名2 read(write), ...;
  14. # 释放表锁
  15. unlock tables;

Myisam的读写锁调度是写优先,这也是myisam不适合做写为主表的引擎。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞

行锁

可同时操作不同行
无效索引会导致行锁升级为表锁;(此时索引会遍历整个列)

间隙锁(eg: 当锁定了col的1-6的范围时,这是再想插入一个col=2进去,会锁住)
手动行锁 select xxx ... for update

行锁分析

  1. mysql> show status like 'innodb_row_lock%';
  2. +-------------------------------+--------+
  3. | Variable_name | Value |
  4. +-------------------------------+--------+
  5. | Innodb_row_lock_current_waits | 0 | 当前正在等待锁定的数量;
  6. | Innodb_row_lock_time | 212969 | 从系统启动到现在锁定总时间长度; *
  7. | Innodb_row_lock_time_avg | 42593 | 每次等待所花平均时间; *
  8. | Innodb_row_lock_time_max | 51034 | 从系统启动到现在等待最常的一次所花的时间;
  9. | Innodb_row_lock_waits | 5 | 系统启动后到现在总共等待的次数; *
  10. +-------------------------------+--------+
  11. 5 rows in set (0.00 sec)