为什么数据库需要锁?
数据库是一个多用户使用的共享资源,当多个用户并发的存取数据时吧,在数据库中会产生多个事务同时的存取同一数据库的情况,若对并发操作不加以控制,就可能会读取和存储不正确的数据,破坏数据库的一致性。
数据库中锁的分类有哪些?
按锁的粒度划分:表级锁、行级锁、页级锁
按锁级别划分:共享锁、排它锁、意向锁
共享(读)锁、排他(写)锁、意向共享(读)锁、意向排他(写)锁;
按面向编程的思想划分:乐观锁、悲观锁
注意:看到这些锁不要脑袋发懵,我的理解是,这些锁底层可以说都是通过面向编程的锁演化来的
一般写锁都是一种悲观锁,写的时候阻塞其他人的任何操作,而
表级锁/行级锁/页面锁
可以使用读锁或者写锁来实现
分别介绍一下不同类型锁的作用?
悲观锁
:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁,传统的关系型数据库里边就用到了很多这种锁机制,比如行锁
,表锁
,写锁
等,都是在做操作之前先上锁。
乐观锁
:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候
会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制,乐观锁
适用于多读的应用类型
,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制
的其实都是提供的乐观锁。
表级锁
:引擎 MyISAM
,直接锁定整张表,如果是表共享读锁
(Table Read Lock),则其他线程可以对表进行读操作(它不会阻塞其他用户对同一表的读
请求,但会阻塞 对同一表的写操作),如果是表独占写锁
(Table Write Lock),其它进程既不能对表进行读操作也无法对表进行写操作(它会阻塞其他线程对同一表的读和写
请求)。
MyISAM存储引擎支持:
表共享的读锁
和表独占的写锁
。
MyISAM在执行查询语句(Select)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户控制,是MySQL SERVER端自动完成的。
页级锁
:引擎 BDB
,表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录
行级锁
:引擎 INNODB
, 仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作,InnoDB也支持两种形式的行级锁,一种是共享行级锁(读锁),一种是排他行级锁(写锁)。
InnoDB行锁是通过给索引上的索引项加锁来实现的,而不是给表的行记录加锁实现的,这就意味着,只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁(因为没有索引嘛,存储引擎只能给所有的行都加锁,和表锁一样,把记录返回给MySQL Server,它会筛选出符合条件的行进行加锁,其余的行就会释放锁)!
上述三种锁的特性可大致归纳如下:
-
1) 表级锁:开销小,加锁快;不会出现死锁,
锁定粒度大
,发生锁冲突的概率最高,并发度最低。 -
2) 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
-
3) 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
三种锁各有各的特点,若仅从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如WEB应用,行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
MySQL不同引擎支持的锁的区别?
我们可以使用这个命令查看mysql支持的存储引擎:
SHOW ENGINES;
最常用的两种存储引擎为:InnoDB
和MyISAM
,下面就使用表格的方式看看这个常用存储引擎的区别:
对比项 | InnoDB | MyISAM |
---|---|---|
主外键 | 支持 | 不支持 |
事务 | 支持 | 不支持 |
行表页锁 | 行锁:操作时只锁某一行,不对其它行有影响,适合高并发操作 | 表锁:即时操作一条记录也会锁住整张表,不适合高并发操作 |
缓存 | 不仅缓存索引,还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响 | 只缓存索引,不缓存真实数据 |
表空间 | 大 | 小 |
关注点 | 事务 | 性能 |
默认安装 | 是 | 是 |