MySQL学习笔记(五):MySQL表级锁和行级锁

一:概述web

相对其余数据库而言,MySQL的锁机制比较简单,其最显著的特色是不一样的存储引擎支持不一样的锁机制。好比,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);InnoDB存储引擎既支持行级锁( row-level locking),也支持表级锁,但默认状况下是采用行级锁。数据库

MySQL主要的两种锁的特性可大体概括以下:
 表级锁: 开销小,加锁快;不会出现死锁(由于MyISAM会一次性得到SQL所需的所有锁);锁定粒度大,发生锁冲突的几率最高,并发度最低。
 行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高。

session

考虑上述特色,表级锁使用与并发性不高,以查询为主,少许更新的应用,好比小型的web应用;而行级锁适用于高并发环境下,对事务完整性要求较高的系统,如在线事务处理系统。并发

 

二:MyISAM锁细述高并发

(1). 锁模式优化

MySQL的表级锁有两种模式: 表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。spa

(2).  如何加锁线程

当MyISAM在执行查询语句时,会自动给涉及到表加读锁,在执行更新操做时,会加写锁。固然用户也能够用LOCK TABLE 去显式的加锁。显式的加锁通常是应用于:须要在一个时间点实现多个表的一致性读取,否则的话,可能读第一个表时,其余表因为还没进行读操做,没有自动加锁,可能数据会发生改变。而且显示加锁后只能访问加锁的表,不能访问其余表。排序

(3). 并发插入索引

MyISAM存储引擎有个系统变量 concurrent_insert,专门用来控制并发插入的行为,能够取 0 , 1 , 2。

0表示不容许并发插入,1表示表中间没有删除的行时能够在表末尾插入,2表示老是能够插入。

通常若是对并发要求比较高的状况下,能够设置为2,老是能够插入,而后按期在数据库空闲时间对表进行optimize。

(4). 锁的调度

须要注意的是,其中读操做不会阻塞其余用户对同一表的读请求,但会阻塞对同一表的写请求;而且当写锁和读锁同时被申请时,优先得到写锁,这也这正是表级锁发生锁冲突几率最高的缘由,由于写锁可能会一直阻塞读锁,因此不适合有大量写操做的环境下工做。这一问题能够经过设置low-priority-updates这一启动参数来下降写的优先级。
虽然写锁优先于读锁获取,可是长时间的查询操做也可能会让写操做饿死,因此尽可能避免一条SQL语句执行全部的查询,应该进行必要的分解。

 

三:InnoDB锁细述

因为InnoDB支持事务,并默认是使用行级锁,因此InnoDB的锁问题和MyISAM锁问题仍是有蛮大差异的。

(1). 锁模式

共享锁(S)和排他锁(X),分别相似于MyISAM的读锁和写锁。对于 UPDATE、 DELETE 和 INSERT 语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通 SELECT 语句,InnoDB不会加任何锁。

(2). 如何加锁

能够显式的加锁,用lock in share mode 显式的加共享锁,用 for update 显式的加排他锁。

须要注意的是,若是线程A加了共享锁后,线程B对同一个表加了共享锁,那么两个线程须要进行更新操做时会产生死锁。因此,进行更新操做时最好加排他锁。

(3). InnoDB行锁的实现方式——索引加锁

这一点与Oracle不一样,因此这也意味着(重要):1. 只有经过索引条件检索数据时,InnoDB才会使用行级锁,不然会使用表级锁。 2. 即便是访问不一样行的记录,若是使用的是相同的索引键,会发生锁冲突。 3. 若是数据表建有多个索引时,能够经过不一样的索引锁定不一样的行。

(4). 间隙锁

InnoDB支持事务,为了知足隔离级别的要求,InnoDB有个间隙锁,当使用范围查找时,InnoDB会给知足key范围要求,但实际并不存在的记录加锁。例如:select * from user where id > 100 for updata 会给ID>100的记录加排他锁,知足这个范围,但不存在的记录,会加间隙锁,这样能够避免幻读,避免读取的时候插入知足条件的记录。

(5). 隔离级别与锁

通常来讲,隔离级别越高,加锁就越严格。这样,产生锁冲突的几率就越大,通常实际应用中,经过优化应用逻辑,选用 可提交读 级别就够了。对于一些确实须要更高隔离级别的事务,再经过set session transaction isolation level+"级别" 来动态改变知足需求。

 

四:死锁

MyISAM是没有死锁问题的,由于他会一次性得到全部的锁。InnoDB发生死锁后通常能自动检测到,并使一个事务释放锁并回退,另外一个事务得到锁,继续完成事务。

在应用中,能够经过以下方式来尽量的避免死锁:

(1) 若是不一样的程序会并发的存取多个表,应尽可能约定以相同的顺序来访问表,这样能够大大下降产生死锁的机会。

(2) 在程序以批量方式处理数据时,若是事先对数据排序,保证每一个线程按固定的顺序来处理记录,也能够大大的下降出现死锁的可能。

相关文章
相关标签/搜索