提出问题
本章节内容开篇先提出问题,我们简化这个问题。假设有一个单向链表,每一个单元记录着上一个单元的key,每一个单元且只有一个值。
那么如果有两个客户端同时向这个链表追加一个值得时候,会发生什么。显然这个就是并发问题了。本章节粗略介绍了 MYSQL 是如何解决这个问题的。
解决思路
解决问题的办法就是加锁。根据锁类型来分,分为两种,而这两种锁,在外界有太多的说法。
而本书使用的名词,叫读锁(Read Lock,S锁,共享锁,都是指的同一种),写锁(Write Lock,X锁,排它锁),更标准的做法,其实就是叫读,写锁。
共享锁与排它锁这两个叫法实际来源于这两种锁的特征。
思考
在本章节,没有去描述锁技术的具体实现,也只是非常浅的描述了这两种锁的区别,即对数据片加上写锁后,其他用户不允许对该数据片进行读和写。对数据片加上读锁后,其他用户也可以对该数据片进行读取,但是不可以进行写操作。
在这里,本章节描述到:
对数据库来说,随时随地都会发生锁定。当某一用户修改某一部分数据的时候,Mysql 会禁止其他用户读取同一数据,大多数时候,Mysql 都是以透明的方式来实现锁的管理。
在此之前,我在看视频的时候,那个讲师说到过,为什么大多数时候,我们不去加锁,不去用事务,程序也能正常运行?那是因为 Mysql 默认替我们做了那些事情。
然后在上一章节中也有提到过,服务器通过存储引擎 API 与引擎进行通讯,这个 API 接口对于查询层上来说是透明的。
可以看出Mysql会默认在大多数时候会对数据自动进行加锁(当然这中间是有根据查询语句判断加什么锁的)。
以上是对锁的类型进行了分类的简单说明,后面说到了锁粒度进行了说明,只写了两种,即表锁和行锁(书中介绍到这两种锁是最重要的锁策略)。
锁粒度
加锁是为了防止在并发状态下的数据冲突,而加锁也会带来性能上的消耗,每一种锁都会有三种操作,即检查锁,获得锁,释放锁,都是开销。
每一种锁粒度带来的消耗也不一样,开销也会不一样。提高共享资源的并发性就是让锁定数据片对象更有选择性,即只对要修改的数据片进行加锁
开销最小的是表锁。行锁开销最大。表锁是由服务器实现的,而行锁是由存储引擎实现的。出现并发读写状况的话,写锁的优先级要高于读锁。
服务器是完全不了解存储引擎的锁实现方式的。虽然存储引擎管理自己的锁。
但是 Mysql 本身也能使用各种有效的表锁,例如在一些情况下,Mysql服务器会自动选择表锁,而不用去考虑存储引擎用的什么锁。
例如 alter table,进行表的结构处理,会自动为这个语句加上表写锁,防止并发情况下的数据冲突。
原文链接: 高性能 Mysql 第一章第二节 并发控制