介绍: 锁是计算机协调多个进程或线程并发访问某一资源的机制。锁保证数据并发访问的一致性、有效性;锁冲突也是影响数据库并发访问性能的一个重要因素。锁是Mysql在服务器层和存储引擎层的的并发控制。
深入Mysql锁机制
(1)锁机制
- 共享锁(读锁): 其他事务可以读,但不能写。
- 排他锁(写锁): 其他事务不能读取,也不能写。
(2)Mysql粒子锁
Mysql不同的存储引擎支持不同的锁机制,都用自己的方式展示着锁机制:
- MyISAM 和 MEMORY 存储引擎采用的是表级锁(table-level locking)
- BDB 存储引擎采用的是页面锁(page-level locking),但也支持表级锁
- InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。
(3)深入Mysql粒子锁
创建一个用户表,存储引擎用myisam
CREATE TABLE `user` (
`uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` varchar(30) DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
show open tables #查看表加锁情况
lock table 表名 read/write #加锁,多个表可以用","隔开
unlock tables; #释放锁
![](http://dsvip1.vip/mysql23.png)
创建两条数据库连接,当我们对表加read锁时,我们加锁线程也只能读数据,不能修改数据,并且不可以操作其他表。其他线程也可以读数据,对数据进行修改时会发生堵塞,可以操作其他表。只有等待加锁线程释放锁。
![](http://dsvip1.vip/mysql24.png)
当我们添加write锁,我们加锁线程不仅可以读数据还可以修改数据,没释放锁的时候不可以操作其他表,其他线程读数会发生阻塞,直到释放锁。
show status like 'table%' #分析表锁定
![](http://dsvip1.vip/mysql25.png)
- Table_ locks_ immediate: 产生表级锁定的次数,表示可以立即获取锁的查询次数,每立即获取锁值加1。
- Table_ locks_ waited: 出现表级锁定争用而发生等待的次数(不能立即获取锁的次数,每等待一次锁值加1), 此值高则说明存在着较严重的表级锁争用情况。
使用myisam做存储引擎我们要偏重读操作。
innodb和myisam的不同在于,innodb支持事务,采用的行锁:
1)事务的ACID特性:
-
原子性(Atomicity) : 事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
-
一致性(Consistent) : 在事务开始和完成时,数据都必须保持一致状态。 这意味着所有相关的数据规则都必须应用于事务的修改以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
-
隔离性(Isolation) : 数据库系统提供一定的隔离机制, 保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
-
持久性(Durable): 事务完成之后,它对于数据的修改是永久性的,I即使出现系统故障也能够保持。
2)并发事务带来的问题:
3)隔离级别:
![](http://dsvip1.vip/mysql26.png)
show variables like 'tx_isolation';#查看mysql隔离级别
innodb的行锁:
![](http://dsvip1.vip/mysql27.png)
事务A操作cid=1,事务没有提交的时候,事务B操作cid=1,会发生堵塞。
innodb行锁变表锁:
#innodb默认使用行锁,但是索引失效有时会导致行锁变成表锁。
![](http://dsvip1.vip/mysql28.png)
innodb间隙锁危害:
#当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙
比如:修改1<id<5的数据,id=2的数据即使不存在,也会给id=2加锁。宁愿错杀也不放过。
show status like 'innodb_row_lock%' #分析行锁定。