Mysql锁机制
所属分类 mysql
浏览量 1407
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资源加载方式比较