上几篇博客我们大致讲了一下mysql的底层结构,什么B+tree,什么Hash需要回行啊,再就是讲了mysql优化的explain,这次我们来说说mysql的锁。
mysql锁
锁从性能上分为乐观锁(用版本对比来实现)和悲观锁,乐观锁的性能要比悲观锁高。
从对数据库操作的类型分,分为读锁和写锁(都属于悲观锁)
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。除锁以外的线程只可读,不可以写入。
写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。除锁以外的线程不可以做任何操作。
从对数据操作的粒度分,分为表锁和行锁,再就是不常提到的间隙锁。
我们主要来说表锁和行锁,还有我们的间隙锁。
注意:有锁等待的几乎都为悲观锁
表锁
顾名思义,加了表锁,会将整张表锁住。开销很小,加锁很快,不会出现死锁;锁定粒度大;
我们来看几条命令。以student表为例
加表锁:lock table 表名称 read(write),表名称2 read(write);
lock table student write;
查看表状态(是否被加锁):
show open tables;
内有有一个列为In_use为1的即为已有锁存在。
解锁表:unlock tables;
unlock tables;
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁
在执行增删改操作前,会自动给涉及的表加写锁。
1、对MyISAM表的读操作(加读锁) ,不会阻寒其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
2、对MylSAM表的写操作(加写锁) ,会阻塞其他进程对同一表的读和写操作,只有 当写锁释放后,才会执行其它进程的读写操作
3、MylSAM表不支持行锁,也不支持事务。
行锁
每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小。
说到这要提到我们的ACID了,我们来复习一下。
A(atomicity)原子性:
即事务要么全部做完,要么全部不做,不会出现只做一部分的情形,如A给B转帐,不会出现A的钱少了,B的钱却没有增加的情况,要么全部成功,要么全部失败(回滚)。这一系列的动作可以视为一个原子。
C(consistency)一致性:
指的是事务从一个状态到另一个状态是一致的,如A减少了100,B不可能只增加30。
I(isolation)隔离性:
即一个事务在没有完成数据的提交修改时,对其它事务是不可见的。当然这里有个隔离级别的概念,在不同隔离级别下,这里会有不同的表现形式。
D(durability)持久性:
一旦事务提交,则所做修改就会被永久保存到数据库中。
然后就是我们的并事务处理带来的问题,先过一遍这些都会造成什么后果。
更新丢失(Lost Update)
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每 个事务都不知道其他事务的存在,就会丢失更新问题–最后的更新覆盖了由其 他事务所做的更新。
举例:比如我们同时开启两个线程去售票,卖一张少一张,我们线程A开启事务,同时我们开启线程B,同时查询到余票为10张,卖一张吧。A卖了一张,10-1,剩余9张,我们B线程也卖了一张也是10-1,也剩余9张,提交A,提交B,我们明明卖了两张票,可是数据库得到的确实9,只卖了一张票。
脏读(Dirty Reads)
一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数 据就处于不一致的状态;这时,另一个事务也来读取同一条记录,如果不加控 制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提 交的数据依赖关系。这种现象被形象的叫做“脏读”。 一句话:事务A读取到了事务B已经修改但尚未提交的数据,还在这个数据基 础上做了操作。此时,如果B事务回滚,A读取的数据无效,不符合一致性要求。
不可重读(Non-Repeatable Reads)
一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却读出的数据已经改变、或某些记录已经被删除了!这种现象就叫做“不 可重复读”。 一句话:事务A读取到了事务B已经提交的修改数据,不符合隔离性。
幻读(Phantom Reads) 郑州哪家男科医院好:http://mobile.zztongji120.com/郑州男科医院排名:http://mobile.zztongji120.com/郑州看男科多少钱:http://mobile.zztongji120.com/
一个事务按相同的查询条件重新读取以前检索过的数据,其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。 一句话:事务A读取到了事务B提交的新增数据,不符合隔离性
后面的两个说完MVCC机制也就知道是怎么回事了,暂时放在这里。
这些问题我们再回到我们的数据库吧。