首页   快速返回

Mysql锁机制     所属分类 mysql
MySQL 不同的存储引擎支持不同的锁机制

MyISAM和MEMORY存储引擎 使用 表级锁(table-level locking)
BDB存储引擎使用页面锁(page-level locking),但也支持表级锁
InnoDB存储引擎 支持行级锁(row-level locking) 表级锁, 默认使用行级锁


表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般 

MyISAM表锁
表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)

读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求
写操作,会阻塞其他用户对同一表的读和写操作
当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。



MyISAM执行查询语句(SELECT) 自动给涉及的所有表加读锁,
在执行更新操作 (UPDATE、DELETE、INSERT等)会自动给涉及的表加写锁, 
一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁

查询表级锁争用情况

show status like 'table%';

Variable_name | Value 
Table_locks_immediate | 2979 
Table_locks_waited | 0 


并发插入(Concurrent Inserts)

MyISAM表的读和写是串行的,在一定条件下,支持查询和插入操作的并发进行。 
concurrent_insert,用于控制并发插入行为,其值分别可以为0 1 2

0  不允许并发插入。
1  如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录,默认设置。
2  无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。



InnoDB锁 InnoDB与MyISAM 2个不同点: 支持事务(TRANSACTION) 采用行级锁 InonoD行锁争用情况 show status like 'innodb_row_lock%'; 两种类型的行锁 共享锁(s):又称读锁。 排他锁(X):又称写锁。 update,delete,insert 自动给涉及到的数据加上排他锁 select语句默认不会加任何锁类型 加排他锁可以使用select ... for update 加共享锁可以使用 select ... lock in share mode 加排他锁的数据行在其他事务中不能修改 但可以直接通过select查询数据,因为普通查询没有任何锁机制。 为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。 意向共享锁(IS):事务打算给数据行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。 意向排他锁(IX):事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。 InnoDB行锁实现方式 InnoDB行锁通过给索引上的索引项加锁来实现 只有通过索引条件检索数据,InnoDB才使用行级锁,否则将使用表锁! 这个很重要!!! 是否走索引 看执行计划 explain select * from tab_with_index where name = 1 explain select * from tab_with_index where name = '1' 间隙锁(Next-Key锁) 用范围条件而不是相等条件检索数据 , 并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁 对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁 (Next-Key锁)。 Select * from emp where empid > 100 for update; 范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。 使用间隙锁的目的 1 为了防止幻读,以满足相关隔离级别的要求 2 满足其恢复和复制的需要 在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。 因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。 使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁 InnoDB 行锁基于索引实现,如果不通过索引访问数据,使用表锁。 通过InnoDB锁特性 , 优化锁性能 ,减少锁冲突和死锁 尽量使用较低的隔离级别 ,精心设计索引,尽量使用索引访问数据,使加锁更精确,减少锁冲突几率 选择合理的事务大小,小事务发生锁冲突的几率也更小 给记录集显式加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁; 访问多个表时,尽量以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。减少死锁的机会 尽量用相等条件访问数据,避免间隙锁对并发插入的影响, 不要申请超过实际需要的锁级别 ,查询时不要显示加锁,除非有需要 对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能。 JAVA锁机制

上一篇     下一篇
使用aql更新lua脚本

metaspace OOM 实例

规则引擎easyrules

mysql连接信息查看

Java锁机制

java资源加载方式比较