写点什么

mysql 锁及数据一致性总结

作者:阿呆
  • 2023-03-04
    北京
  • 本文字数:1808 字

    阅读完需:约 6 分钟

mysql锁及数据一致性总结

简介

本文将从以下几方面展开介绍

1、msyql 锁的类型:行锁,表锁,页锁,乐观锁,悲观锁等

2、mysql 脏读、不可重复读、幻读的概念及如何避免

3、mysql 如何保证数据一致性,以及 mysql 和 redis 的数据一致性如何保证?

mysql 锁

在本节,我们针对不同粒度的锁进行介绍:行锁、页锁,表锁,介绍 mysql 不同引擎使用的粒度锁及优劣,最后,针对 innodb 中的锁进行更为详细的讲述。

粒度锁:行锁、表锁、页锁

首先,我们来看下 mysql 不同的粒度锁之间的优劣,页锁其实处于行锁和表锁之间。innodb 支持行锁和表锁,但默认是行锁。

图1:行锁、表锁、页锁特点


InnoDB 锁模式

InnoDB 实现了两种类型的行锁:行锁是加在索引上的,只有通过索引条件检索数据,才会使用行锁

  • 共享锁(S):共享锁又称读锁,简称 S 锁,共享锁是多个事务对同一数据可以共享一把锁,只能读不能修改

  • 排他锁(X):排他锁又称写锁,简称 X 锁,不能与其他事务共享(包含读锁和写锁),但是获取到排他锁的事务时可以对数据进行读取和修改


我们都知道,innodb 支持行锁和表锁,因此,为了允许这两种锁共存,还有两种意向锁(Intention Locks),这两种意向锁都是表锁

  • 意向共享锁(IS):事务打算加 S 锁时,必须先取得该表的 IS 锁

  • 意向排他锁(IX):事务打算加 X 锁时,必须先取得该表的 IX 锁


InnoDB 加锁方法

  • 意向锁是 InnoDB 自动加的, 不需用户干预。

  • 对于 UPDATE、 DELETE 和 INSERT 语句, InnoDB 会自动给涉及数据集加排他锁(X);

  • 对于普通 SELECT 语句,InnoDB 不会加任何锁;

  • 事务可以通过以下语句显式给记录集加共享锁或排他锁:

共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。但是如果当前事务需要对该记录进行更新操作,则很有可能造成死锁。排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。其他 session 可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁


InnoDB 间隙锁

当我们使用范围条件查询时,InnoDB 会给符合条件的数据索引加锁,对于符合条件范围内,但数据还不存在的间隙,InnoDB 也会加锁,就是所谓的间隙锁(Next-key 锁),因此,在并发插入时,我们尽量要用等于来更新数据,避免使用范围条件。而 InnoDB 使用间隙锁的目的,也是为了防止幻读


乐观锁和悲观锁

  • 乐观锁:认为每次去 select 数据时,都认为不会修改,所以不会上锁,但在更新的时候回去判断是否有人更新数据,可以用版本号等机制控制;

  • 悲观锁:认为肯定会发生冲突,认为每次去获取数据时别人都会修改,因此每次拿数据时都会上锁。而上文提到的行锁、表锁、页锁都是悲观锁的不同实现。


脏读、不可重复读、幻读

本节我们针对数据库中脏读、不可重复读、幻读进行详细的介绍,并介绍数据库是如何解决这几个问题。

数据库事务 ACID

我们首先来了解数据库事务的四大特性,简称 ACID,分别是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性:事务包含的数据库操作,要么全部成功,要么失败了全部回滚

  • 一致性:一个事务执行前后必须一致,比如转账:A+B 的钱总共 1000,在 A 向 B 转账 100 后,两个人加起来的钱还应该是 1000

  • 隔离性:一个事务为提交时,结果对其他事务是否可见,级别一般包含:读未提交、读提交、可重复读、串行化访问

  • 持久性:事务一旦提交,在数据库中永久生效,即使数据库故障也不会丢失

脏读、不可重复读、幻读

接下来我们了解这三种由于并发访问,从而导致的数据库读取问题

  • 脏读:读取未提交数据,eg:A 事务在获取数据时,B 事务已经更改了数据,但事务未完成,在 A 获取数据后,B 事务失败回滚,因此 A 事务获取到的数据是错误的。

  • 不可重复读:前后多次读取的数据不一致,eg:A 事务开始时获取数据,然后 B 事务修改了数据(针对 update 操作),A 再次获取数据,前后获取的数据不一致。

  • 幻读:前后多次读取的数据量不一致,eg:A 事务开始时获取数据,然后 B 事务 insert 了数据(针对 insert 或 delete 操作),A 再次获取,发现获取的数据量比上次要多。

数据库隔离级别

mysql 数据库隔离级别分为四种,默认为可重复读,能够解决脏读、不可重复读的问题。


如何保证数据一致性

mysql 日志:binlog、relog、unlog

可以到参考链接 3 中学习


参考链接

1、漫谈 MySQL 的锁机制:https://developer.aliyun.com/article/686688

2、MySQL 锁总结:https://zhuanlan.zhihu.com/p/29150809

3、mysql 日志:https://www.toutiao.com/article/7146212778104160802/?wid=1678002274213

发布于: 2023-03-04阅读数: 37
用户头像

阿呆

关注

坚守准则,认真做事。 2018-05-22 加入

职位:360资深后台开发,主要负责DevOps平台开发 技术:Python 爱好:炉石传说

评论

发布
暂无评论
mysql锁及数据一致性总结_MySQL_阿呆_InfoQ写作社区