MySQL/InnoDB 的加锁规则

 

在排查线上问题时候可能会遇到因为数据库加锁的原因导致程序执行缓慢或者数据卡死的情况发生,下面将简单为大家介绍...



在排查线上问题时候可能会遇到因为数据库加锁的原因导致程序执行缓慢或者数据卡死的情况发生,下面将简单为大家介绍下数据库加锁的过程,在了解数据加锁前需要先对以下概念做简单了解:

1)        MySql数据库存储引擎

2)        数据库的隔离级别

3)        Mysql数据库的并发控制协议

4)        死锁分析

MySql数据库表的存储类型

下面对mysql常用的存储引擎类型及其特点做了个汇总如下:

存储引擎类型

优点

缺点

MyISAM

静态MYISAM-->表字段长度一样,存取更新效率高,受损易修复

动态MYISAM-->存储空间小,记录长度不一,多次存储后数据离散,内存碎片多,需要经常碎片整理

压缩MYISAM-->添加了压缩工具,占用空间减小,读取时需要解压缩

不支持事务

不支持锁

不支持外键约束

InnoDB

MYISAM的优化,支持事务、锁、外键约束

memory(heap)

存于内存,存取速度快

存于内存,无法持久化?只适合做临时表

archive

存储大量数据,常用于日志记录和聚合分析

只支持select 和 insert操作,不支持索引

CSV

存储引擎把数据以逗号分隔的格式存储在文本文件中

*备注:查看数据库搜索引擎的命令 show engines;

从以上表的对比中可以发现innoDB是支持事务、锁、外键约束的,innoDB也是数据库中常采用的一种存储方式,下面就innoDB存储引擎展开详细介绍;

Mysql数据库的隔离级别

事务隔离级别的不同也会导致执行结果的不同;

关系数据库标准中有四个事务隔离级别:

未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别

可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读

串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

innoDB 型数据库在未修改的时候默认是采用RR形式的,正如上面介绍,RR消除了不可重复读的情况,但是仍然存在幻读发生;InnoDB存储引擎通过引入MVCC的方式,解决了幻读问题;

*备注:幻读是指有多个事务同时操作时,一个事务读取某个范围的数据行时,另一个事务对该范围的数据插入了新的数据行,当重新读取该范围的数据时发现数据已经发生了变化,出现了“幻影”行;

*注:查看系统级事务隔离级别命令 SELECT @@global.tx_isolation;查看会话级事务级别命令SELECT @@tx_isolation;数据库的隔离级别可以根据自身需要调整,修改隔离级别的命令set transactionisolation level XXX

Mysql innoDB存储引擎的并发控制协议

Mysql innoDB存储引擎实现的是基于多版本的并发控制协议----MVCC,MVCC的一大好处就是读不加锁,读写不冲突,在读多写少的情况下,读写不冲突极大的增加了系统性能;

MVCC读操作分为两类:快照读(snapshot read)和当前读(current read);快照读读取的是当前可见的版本,有可能是历史版本,操作不加锁,当前读读取的是记录的最新版本,并且当前读返回的记录都会加锁,避免被其他事务修改;

MySQL InnoDB 的简单快照读和当前读的分类:

快照读

select * from  table where ?;

当前读

select * from table where ? lock in share mode;

select * from table where ? for update;

insert into table values (…);

update table set ? where ?;

delete from table where ?;

*所有的快照读都是加S 锁 (共享锁)外,当前读都加的是 X 锁 (排它锁)。

INNODB常见的死锁案例:

  1. 1.      两个事务互相等待对方的资源引起的死锁,通常在innodb中,mysql会去检查,如果发生了死锁,会主动终止掉 (回滚损失最小的)
事务1



事务2

  1. 2.      两个事务加锁的过程中,出现了同时需要对重叠部分进行加锁。
事务1



事务2



通过上述案例,我们可以得出:

死锁是由两个或者两个以上的进程在执行时,因互相争夺资源而引起的一种互相等待的现象。如果没有外界的干预,将无法继续进行下去。

可以通过死锁日志来分析,产生死锁的具体原因。也可以在客户端使用



查询最近一次死锁的情况。查询结果如下:


    关注 商业技术业务端


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册

mysql 相关文章