随笔录--MySQL的事务隔离级别和特点

官方解析

MySQL 事务有四种隔离级别:

  1. 读未提交(Read Uncommitted):事务可以读取未提交的数据,可能会读到脏数据,会导致幻读、不可重复读、脏读等问题;

  2. 读已提交(Read Committed):只能读取已经提交的数据,可以避免脏读问题,但是可能会遇到不可重复读、幻读问题;

  3. 可重复读(Repeatable Read):保证同一个事务中多次读取同一数据的结果是一致的,避免了脏读和不可重复读问题,但是可能会遇到幻读问题;

  4. 序列化(Serializable):最高的隔离级别,可以避免所有并发问题,但是并发性能非常低,开销很大。

MySQL 的默认隔离级别是可重复读(Repeatable Read)。

其中,脏读指一个事务读到了另一个事务未提交的数据不可重复读指同一个事务多次读取同一数据得到不同结果幻读指同一个事务前后读取的数据集合不一致

在实际使用中,应该根据具体情况选择合适的隔离级别,权衡数据的一致性和并发性能。

图片

查看隔离级别

SELECT @@TRANSACTION_ISOLATION;
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE];

注:mysql 中默认事物隔离级别是可重复读。

图片

图片

图片

图片

在MySQL中事务的隔离级别是为了解决常见的并发问题,在保证数据库性能的同时保持事务的隔离性,常见的并发问题有:

脏读:如果一个事务读到了另一个未提交事务修改过的数据,那就意味着发生了脏读(Dirty Read)。

图片

不可重复读:如果一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值,那就意味着发生了不可重复读(Non-Repeatable Read);

图片

幻读:如果一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,那就意味着发生了幻读(Phantom reading)。

图片

三个并发问题的区别如下:

  • 脏读的重点在于未提交。脏读应该是三个里面最好理解的,其定义很轻易便能理解,一个事务中读取了另外一个事务未提交的数据,是先修改再读;

  • 不可重复读的重点在于对单条数据读取了两遍。T1先读取了一遍,而后T2修改该数据并提交,最后T1再次读取了该数据发现与之前的不同;

  • 幻读的重点在于针对一类条件对一系列数据读取了两遍。比较特殊的点在于幻读是具备条件的查询,这种查询可能查出来的并不只有一条数据,而在两次查询过程中另外一个事务对查询的结果集中的某条数据进行了变动。

针对于上述的并发问题,在 SQL 标准中设立了以下4个隔离级别:

  • READ UNCOMMITTED:未提交读。所有事务都可以看到其他未提交事务的执行结果;

  • READ COMMITTED:已提交读。一个事务只能看见已经提交事务所做的改变;

  • REPEATABLE READ:可重复读。确保了同一事务的多个实例在并发读取数据时,会看到同样的数据行;

  • SERIALIZABLE:可串行化。强制事务串行,并发效率很低。

下面表格展示了在 SQL 标准中规定的并发事务执行过程中可能发生的现象,其中✔️代表可能发生现象,❌代表不可能发生现象:

图片

不同的数据库厂商对 SQL 标准中规定的 4 种隔离级别的支持是不一样的。其中 MySQL 的默认隔离级别为 REPEATABLE READ,即可重复读在该隔离级别下可以很大程度上禁止了幻读现象的发生。

SQL 标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能效率就越低,这四个隔离级别如下:

  • 读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;

  • 读已提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;

  • 可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;

  • 串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;

拓展问题

  • 不同的隔离级别会有不同的特性,那么为什么要设置这么多的隔离级别呢?

  • 不同的隔离级别有哪些实际应用的场景,适合解决什么业务?

  • 每个隔离级别是怎么实现的?

不同的隔离界别有哪些实际应用的场景,适合解决什么业务? 不同的隔离级别适用于不同的场景,下面列举一些实际应用:

  • 读未提交(read uncommitted):适用于数据实时性要求较高的场景,比如一些报表的生成,当数据量大、计算量大时,如果使用较高的隔离级别,可能会出现锁等待导致查询时间过长的情况,而读未提交隔离级别可以避免这种情况的发生。

  • 读已提交(read committed):适用于对数据准确性要求较高的场景,比如金融交易等,由于该隔离级别会在读取时加共享锁,所以可以避免脏读的问题。

  • 可重复读(repeatable read):适用于业务场景较为复杂的情况,比如订单下单和支付,如果使用较低的隔离级别可能会导致支付时查询出的订单状态不正确,从而造成数据不一致的问题,而可重复读隔离级别可以避免这种情况的发生。

  • 串行化(serializable):适用于对数据完整性要求非常高的场景,比如一些高风险的金融交易,由于该隔离级别会对每个事务加排它锁,所以可以避免幻读和不可重复读的问题。不过需要注意的是,该隔离级别的并发性非常低,会影响系统的性能,一般只在必要的情况下才会使用。

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值