锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。 在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用之外,数据也是一种供许多用户共享的资源。如 何保证数据并发访问的一致性、有效性是全部数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的 一个重要因素。从这个角度来讲,锁对数据库而言显得尤为重要,也更加复杂sql
1) 表锁:操做时,会锁定整个表。 2) 行锁:操做时,会锁定当前操做行。数据库
1) 读锁(共享锁):针对同一份数据,多个读操做能够同时进行而不会互相影响 2) 写锁(排它锁):当前操做没有完成以前,它会阻断其余写锁和读锁安全
相对其余数据库而言,MySQL的锁机制比较简单,其最显著的特色是不一样的存储引擎支持不一样的锁机制。下表中罗 列出了各存储引擎对锁的支持状况: 并发
![]()
MySQL这3种锁的特性可大体概括以下 :高并发
偏向MyISAM 存储引擎,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的几率最高,并发度最低。性能
偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高。线程
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度通常设计
简而言之,就是读锁会阻塞写,可是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写。3d
InnoDB 实现了如下两种类型的行锁。指针
对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;
若是不经过索引条件检索数据,那么InnoDB将对表中的全部记录加锁,实际效果跟表锁同样。
当咱们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁; 对于键值在条件范围内但并不存在的记录,叫作 "间隙(GAP)" ,InnoDB也会对这个 "间隙" 加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)
InnoDB存储引擎因为实现了行级锁定,虽然在锁定机制的实现方面带来了性能损耗可能比表锁会更高一些,可是在总体并发处理能力方面要远远因为MyISAM的表锁的。当系统并发量较高的时候,InnoDB的总体性能和MyISAM相比就会有比较明显的优点。
可是,InnoDB的行级锁一样也有其脆弱的一面,当咱们使用不当的时候,可能会让InnoDB的总体性能表现不只不 能比MyISAM高,甚至可能会更差。
- 尽量让全部数据检索都能经过索引来完成,避免无索引行锁升级为表锁。
- 合理设计索引,尽可能缩小锁的范围
- 尽量减小索引条件,及索引范围,避免间隙锁
- 尽可能控制事务大小,减小锁定资源量和时间长度
- 尽可以使用低级别事务隔离(可是须要业务层面知足需求)
MVCC (Multiversion Concurrency Control) 中文全程叫多版本并发控制,是现代数据库(包括 MySQL、Oracle、PostgreSQL 等)引擎实现中经常使用的处理读写冲突的手段,目的在于提升数据库高并发场景下的吞吐性能。
一、事务版本号 二、表的隐藏列。 三、undo log 四、 read view
InnoDB 中 MVCC 的实现方式为:每一行记录都有两个隐藏列:DATA_TRX_ID、DATA_ROLL_PTR(若是没有主键,则还会多一个隐藏的主键列)。
记录最近更新这条行记录的事务 ID,大小为 6 个字节
表示指向该行回滚段(rollback segment)的指针,大小为 7 个字节,InnoDB 即是经过这个指针找到以前版本的数据。该行记录上全部旧版本,在 undo 中都经过链表的形式组织。
行标识(隐藏单调自增 ID),大小为 6 字节,若是表没有主键,InnoDB 会自动生成一个隐藏主键,所以会出现这个列。另外,每条记录的头信息(record header)里都有一个专门的 bit(deleted_flag)来表示当前记录是否已经被删除。