MySQL事务

一、事务概念

  事务是数据库系统提供的一种机制,它能够把一个或多个指令看作一个整体,这些指令要么全部执行,要么全部不执行,不会出现停留在中间过程的状态。事务具有如下特性:
  1. 原子性:事务中的指令要么全部执行,要么全部回滚,不会出现只执行部分指令的情况。
  2. 一致性:事务对数据的修改前后能够满足特定的约束,比如用户A给B转账,当事务完成后两个账户的总金额是相等的。
  3. 持久性:事务一旦提交,那么对数据的修改将是永久的,不会因为某种原因而丢失,比如数据库服务器宕机。
  4. 隔离性:一个事务在执行期间感觉不到别的事务的存在。

二、事务特性

  MySQL中事务支持四种隔离级别,分别是读未提交,读已提交,可重复读和串行化。
  1. 读未提交隔离级别下的事务能够读到别的事务已经修改但还没提交的数据,这种数据具有不确定性,也就是别的事务可能提交修改也可能回滚,出现脏读问题。
  2. 读已提交的隔离级别中事务只会读别的事务已经提交的数据,不会出现脏读,但是随之而来的是不可重复读,同样的查询条件过一会再执行返回的结果集不同,出现有些数据被别的事务修改或者删除了。
  3. 可重复读隔离级别能保证同一查询条件在不同时间都能返回相同的查询结果,一般在第一次读取中对读到的数据加锁,其他事务不能修改或者删除这部分的数据,这样就能够保持可重复读。虽然锁住了修改,但是没有锁新增,别的事务能够写入满足查询条件的数据,出现幻读。
  4. 串行化隔离级别即对读到的数据加锁,同时也锁住其他事务进行新增数据,保证事务的最大独占性。

三、读已提交和可重复读对比

  事务隔离级别越低,数据库并发处理能力就越强,读未提交虽然有很高并发处理能力,但是脏读给数据带来很大不确定性,现实中很少会用这种隔离级别;串行化的数据安全程度最高,但是牺牲了数据库很大的并发处理能力,在数据安全要求很高的场景中才会使用。大多数场景选择读已提交或可重复读,MySQL默认事务隔离级别是可重复读,接下来试验这两种隔离级别在MySQL中的表现。
  1. 我使用版本是5.7.28 MySQL Community Server (GPL),可以通过如下命令更改事务隔离级别: SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
  2. 如图1,先把当前会话隔离级别设置成RC,然后两个会话分别开启事务,事务B更新了teacher_id=3的数据,删除了class_name="class 4"的数据,事务A读取了3次数据,第一次在事务B未修改数据前,第二次在事务B修改数据还未提交,最后一次是在事务B提交修改后,可以看出RC隔离级别消除了脏读,但有不可重复读问题。
  3. 如图2,把当前会话隔离级别设置成RR,两个会话分别开启事务,事务B更新了id=5的数据,然后删除了id=2的数据,最后新增了一条记录,事务A在事务B提交前,提交后再次执行相同查询得到同样结果集,满足可重复读,甚至连新增的记录也没看到,没有出现幻读。之所以出现这种情况是因为MySQL为了能够获得更高并发处理能力,使用了MVCC机制,实际上读到的数据是事务开始前数据库数据快照,并不是实时的数据,因此对数据实时性要求高的场景会有问题,在下篇文章再和大家探讨MVCC机制,快照读,当前读以及数据库的锁机制。

图1:RC隔离级别

 图2:RR隔离级别

 

 

posted @ 2021-01-16 23:32  UpTownCat  阅读(90)  评论(0)    收藏  举报