在生活中锁的例子就很是多了,因此应该很容易理解锁的含义。在计算机领域,能够这样来概述,锁是计算机协调多个进行进程并发访问某一资源的机制。mysql
在数据库中,锁也是一个很是重要的特性,DB的锁是为了支持对数据的并发访问,保证数据的一致性以及处理统一数据时不破坏事务的隔离性和一致性。sql
从锁的机制来看,大体可分为乐观锁和悲观锁两类。无论是乐观锁仍是悲观锁,他们是一种思想,而不是具体的锁,并且不单单在数据库系统中有这种概念。数据库
老是假设最好的状况,每次去拿数据的时候都认为别人不会去修改,因此不上锁。可是在更新数据的时候会判断在这个期间这个数据有没有被更新。并发
在mysql实际使用过程当中,有一种比较经常使用的实现方式:基于数据版本(vserion)记录机制。每当数据更新一次,version自增长1。读取数据记录时,将version值读出,当须要提交更新时,将判断当前version值与读出的值大小比较,若是一致,则进行更新,反之则说明过时,拒绝更新数据。code
老是假设最坏的状况,每次拿数据的时候都认为别人会修改,因此每次拿数据的时候就会上锁,这样其余人想拿这个数据时就会阻塞,直到原来上锁的进程释放锁。目前大多数数据库普遍使用的锁机制就是悲观锁思想,好比行锁/表锁/页锁等。下面会进行一些锁的详细讲解。对象
悲观锁与乐观锁各有优势,使用到的场景不一样,乐观锁实用于多读场景,而悲观锁适用于多写场景。进程
相对其余数据库来讲,Mysql的锁比较简单,但有一个特色,不一样的存储引擎支持不一样锁的粒度。事务
表锁:颗粒度最大,锁冲突的几率变大,并发度最低;开销小,加锁快,不会死锁。资源
页锁:mysql特有的,粒度在表锁与行锁之间,因此获取锁资源的时间上,并发度上也是介于表锁和行锁之间,同时,页锁也会出现死锁的状况。io
行锁:颗粒度最小,锁冲突几率小,并发最高;开销大,加锁慢,容易死锁。
表锁适合以查询为主的业务,行锁更适合于有并发更新少许数据且有并发查询的业务。
不一样引擎支持锁的粒度
引擎 | 表锁 | 页锁 | 行锁 |
---|---|---|---|
InnoDB | ✔ | × | ✔ |
MyISAM | ✔ | × | × |
BerkeleyDB | × | ✔ | × |
InnoDB存储引擎还存在着不一样类型的锁,其中就包含下面两种标准的行级锁。
共享锁 S:Shared Lock 读锁 容许事务去读一行数据,阻止其余事务得到相同数据集的排他锁。
若事务T对数据对象A加上S锁,则事务T能够读A但不能修改A,其余事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其余事务能够读A,但在T释放A上的S锁以前不能对A作任何修改。
排他锁 X:Exclusive Lock,写锁 容许获取排他锁的事务更新数据,阻止其余事务取得相同的数据集共享读锁和排他写锁 。
若事务T对数据对象A加上X锁,事务T能够读A也能够修改A,其余事务不能再对A加任何锁,直到T释放A上的锁。加过排他锁的数据行在其余事务种是不能修改数据的,也不能经过for update和lock in share mode锁的方式查询数据,但能够直接经过select …from…查询数据,由于普通查询没有任何锁机制。
共享锁 S 与 排他锁 X 兼容性
锁类型 | S锁 | X锁 |
---|---|---|
S锁 | ✔ | X |
X锁 | X | X |
另外,为了实现多粒度锁机制,同时容许多粒度锁机制,InnoDB还有两种意向锁,均为表锁。
意向共享锁 IS: 事务打算给数据行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。 (表达一个事务想要获取一张表中某几行的共享锁) 。
意向排他锁 IX: 事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。( 表达一个事务想要获取一张表中某几行的排他锁)。
意向共享锁 S 与 意向 排他锁 X 兼容性
锁类型 | IS | IX | S | X |
---|---|---|---|---|
IS | ✔ | ✔ | ✔ | X |
IX | ✔ | ✔ | X | X |
S | ✔ | X | ✔ | X |
X | X | X | X | X |