事务与锁介绍(1)

1.事务概念介绍

事务是一系列数据库操作的有序集合
事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性 (isolation)和持久性(durability)的缩写。

  • 事务的原子性:事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据改操作要全部执行,要么全部不执行。
  • 事务的一致性:指在一个事务执行之前和执行之后数据库都必须处于一致性状态。这种特性称为事务的一致性。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。
  • 事务的隔离性:隔离性指并发的事务对数据的操作是相互隔离的,具体隔离哪些操作需要根据隔离等级来判定。
  • 事务的持久性:持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。

通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么撤销不执行。

2.mysql读写锁

mysql中有多种加锁机制:

1.共享锁(Share locks简记为S锁):又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。共享锁是造成上锁对象必须被大家共享,它排斥 排他锁,因此别的会话不能独占资源对其修改(“修改”会先给修改对象加上 排他锁 的)。但不排斥其他共享锁,所以一个对象可被多个会话同时加上共享锁。

2.排它锁(Exclusivelocks简记为X锁):又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。排他锁很好理解,是自己独占资源。其它会话想再在同一对象上加共享或排他锁都是不允许的。不过其它会话可以读,这也证明普通的读是不上锁的。如果查的对象被修改,查询操作还会会被重定向到对应的撤销块(原来的数据),以保证事务事物隔离和读一致;

3.更新锁(简记为U锁):用来预定要对此对象施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的对象将要被更新时,则升级为X锁,主要是用来防止死锁的。因为使用共享锁时,修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为排它锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个对象申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。

3.事务操作中可能的问题

脏读

脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。

不可重复读

不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。

这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。

一种更易理解的说法是:在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。

不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题。

幻读

事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交。
这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,称为幻读。
幻读和不可重复读主要是前者是针对数据的增删导致的前后读取不一致,后者则是针对同一条数据的修改导致的前后读取不一致。

4.事务隔离等级

不同的事务隔离等级可以解决不同的事务并发问题

Read Uncommitted (读未提交)

加锁机制:
事务在读数据的时候不对数据加锁。
事务在修改数据的时候对数据增加行级X排他锁,在事务结束时释放(这点和有些地方说法不同,读者可以自行实验证明)。

各问题是否会出现
脏读:
A事务修改一行数据,加上了X锁;
事务B在A提交前读该行数据,为什么可以读取,看以下官网原文

Transactions running at the READ UNCOMMITTED level do not issue shared locks to prevent other transactions from modifying data read by the current transaction. READ UNCOMMITTED transactions are also not blocked by exclusive locks that would prevent the current transaction from reading rows that have been modified but not committed by other transactions. When this option is set, it is possible to read uncommitted modifications, which are called dirty reads. Values in the data can be changed and rows can appear or disappear in the data set before the end of the transaction.

Read Uncommitted事务隔离级别没有使用共享锁去阻止其他事务修改当前事务读取的数据。READ UNCOMMITTED事务也不会使得独占锁阻塞当前事务读取已被修改但未被其他事务提交的行。设置此隔离级别,可以读取未提交的修改,称为脏读——在事务结束前,数据中的值可能被改变,行也可能出现或者消失。

所以会有脏读的问题
不可重复读:
事务A读取某一数据,不加锁;
事务B读取并修改了该数据,加X锁,随后提交,释放锁;
A为了对读取值进行检验而再次读取该数据,便读到了事务B已提交的修改,第一次读取不可重复。所以会有不可重复读的问题。
幻读:
事务A读取全部数据,不加锁;
事务B新增一条数据;
A再次读取全部数据,发现多了一条。所以会有幻读的问题。

Read committed(读已提交)(这里介绍的是不用mvcc的情况,与真实情况有出入)

事务对当前被读取的数据加 行级S锁,一旦读完该行,立即释放该锁;
事务在修改数据的时候对数据增加行级X排他锁,在事务结束时释放。

各问题是否会出现
脏读:
A事务修改一行数据,加上了X锁;
事务B在A提交前去读该行数据,无法读取。所以不会有脏读的问题
不可重复读:
事务A读取某一数据,读完立刻解S锁;
事务B可以修改该数据,加X锁,随后提交,释放X锁;
A为了对读取值进行检验而再次读取该数据,便读到了事务B已提交的修改,第一次读取不可重复。所以会有不可重复读的问题。
幻读:
事务A读取全部数据,读完立刻解锁;
事务B新增一条数据;
A再次读取全部数据,发现多了一条。所以会有幻读的问题。

Repeatable read(可重复读)(这里介绍的是不用mvcc的情况,与真实情况有较大出入)

事务对当前被读取的数据加 行级S锁,在事务结束时释放。
事务在修改数据的时候对数据增加行级X排他锁,在事务结束时释放。

各问题是否会出现
脏读:
A事务修改一行数据,加X锁;
事务B在A提交前去读该行数据,无法读取。所以不会有脏读的问题
不可重复读:
事务A读取某一数据,加S锁;
事务B试图修改了该数据,有S锁无法修改,
A为了对读取值进行检验而再次读取该数据,其他事务无法修改该数据,第一次读取可重复。所以不会有不可重复读的问题。
幻读:
事务A读取全部数据;
事务B新增一条数据;
A再次读取全部数据,发现多了一条。所以会有幻读的问题。

Serializable(串行化)

事务对当前被读取的数据加 范围S锁,在事务结束时释放。
事务在修改数据的时候对数据增加范围X排他锁,在事务结束时释放。

各问题是否会出现
脏读:
A事务修改一行数据,加X锁;
事务B在A提交前去读该行数据,无法读取。所以不会有脏读的问题
不可重复读:
事务A读取某一数据,加S锁;
事务B试图修改了该数据,有S锁无法修改,
A为了对读取值进行检验而再次读取该数据,其他事务无法修改该数据,第一次读取可重复。所以不会有不可重复读的问题。
幻读:
事务A读取全部数据,对根据索引判断的范围(没有根据索引查询就会加在主键上)加锁(对于范围的指定这里不详细说明了,比较复杂);
事务B新增一条数据,如果在A读取产生的加锁判断范围内则不能新增,因为该判断范围内对应的行数据已被锁定,不论是否存在;
所以不会有幻读的问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值