锁的分类
- 从数据操作的类型(读、写)分
- 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
- 当前session不能读其他表,也不能修改
- 写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。
- 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
- 从对数据操作的颗粒度
- 表锁
- MyIASM存储引擎
- 开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低
- 行锁
- InnoDB存储引擎
- 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 支持事务
- 行级锁
- 表锁
表锁
表共享读锁,独占写锁
# 查看当前数据库中表的上锁情况:0 表示未上锁mysql> show open tables;+--------------------+----------------------------------------------------+--------+-------------+| Database | Table | In_use | Name_locked |+--------------------+----------------------------------------------------+--------+-------------+| performance_schema | events_waits_history | 0 | 0 || performance_schema | events_waits_summary_global_by_event_name | 0 | 0 || performance_schema | setup_timers | 0 | 0 || performance_schema | events_waits_history_long | 0 | 0 || performance_schema | events_statements_summary_by_digest | 0 | 0 |....# 添加锁lock table 表名1 read(write), 表名2 read(write), ...;# 释放表锁unlock tables;
Myisam的读写锁调度是写优先,这也是myisam不适合做写为主表的引擎。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞
行锁
可同时操作不同行
无效索引会导致行锁升级为表锁;(此时索引会遍历整个列)
间隙锁(eg: 当锁定了col的1-6的范围时,这是再想插入一个col=2进去,会锁住)
手动行锁 select xxx ... for update
行锁分析
mysql> show status like 'innodb_row_lock%';+-------------------------------+--------+| Variable_name | Value |+-------------------------------+--------+| Innodb_row_lock_current_waits | 0 | 当前正在等待锁定的数量;| Innodb_row_lock_time | 212969 | 从系统启动到现在锁定总时间长度; *| Innodb_row_lock_time_avg | 42593 | 每次等待所花平均时间; *| Innodb_row_lock_time_max | 51034 | 从系统启动到现在等待最常的一次所花的时间;| Innodb_row_lock_waits | 5 | 系统启动后到现在总共等待的次数; *+-------------------------------+--------+5 rows in set (0.00 sec)
