mysql二级封锁协议_mysql的两阶段协议(封锁定理,虫洞事务)

数据库事务的隔离性对于数据一致性至关重要。MySQL通过两阶段封锁协议保证事务执行的串行化,以防止数据异常,如丢失修改、脏读、不可重读和幻读。这种协议确保每个事务的操作在结束时释放锁,事务的操作被分为锁请求的扩展阶段和锁释放的收缩阶段。在可重复读隔离级别下,MySQL使用这种协议和行级锁来平衡并发读取效率和数据正确性。
摘要由CSDN通过智能技术生成

我们都知道数据库的事务具有ACID的四个属性:原子性,一致性,隔离性和持久性。然后在多线程操作的情况下,如果不能保证事务的隔离性,就会造成数据的修改丢失(事务2覆盖了事务1的修改结果)、读到脏数据(事务2读到了事务1未回滚的数据)、不可重读(事务2读到了事务1未提交的修改)和幻读(事务2读到了事务1未提交的增删)等。保证事务隔离性可以防止事务出现以上问题,那么数据库又是怎么来保证事务的隔离性的呢?

mysql使用两阶段协议来保证事务执行的串行化从而保证事务的隔离性的。

首先,为了保证数据访问的串行,每个数据资源都有对应的锁(mysql的锁只细化到行级),那么只要保证每个数据资源的访问都是串行化的,然后整个数据库不就可以保证每个数据操作之间的隔离性了么,就是说:

只要每个数据操作都有对应的锁覆盖,然后把每个操作都加上对应的锁,这样可以保证事务执行的串行化么?

答案是:可以保证,但是有个前提是每个事务只包含对一个数据的操作。事实上mysql也默认是这样做的:如果用户没有手动开启事务,那么根据AUTOCOMMIT机制,mysql默认将每一个数据库操作封装成一个事务来处理。

然而实际情况中,很多时候一个事务不只包含一个数据库操作,比如电商平台在生成订单时,一个事务里包含了对订单表、用户表、商品表等的操作。在多线程操作的情况下,如果只用数据库的锁来保证的话,就会出现上面所提到的一些数据异常情况。这时候就需要两阶段协议来保证事务的隔离性了。那么进入今天的主题:

两阶段协议如何保证多事务操作之间的隔离性?

上面说过,只要事务执行是串行的,事务之间就是隔离的,在网上搜索两阶段协议为何能保证串行化,只搜到一个封锁定理:如果事务是良构的且是两阶段的,那么任何一个合法的调度都是可串行化的。既然是定理,那一定是严格成立且可证明的,于是顺藤摸瓜,找到了封锁定理的证明(>这本书的7.5.8.2节)。

首先我们解析命题:

条件:良构的事务、两阶段、合法的调度

结论:是可串行化的。

在书上找到条件的描述:

如果事务的每个READ、WRITE、 UNLOCK都被响应的锁覆盖,且所有的锁都是在事务结束时释放,那么称这样的事物是良构的。(mysql的表和行数据在被操作时,都有对应的锁覆盖)

如果一个事务可以分成两个阶段,只请求封锁的扩展阶段和只释放锁的收缩阶段,那么称之为两阶段的事务。(mysql采用两阶段封锁协议)

调度是一组事务的操作的某种合并结果。(mysql支持多事务并行执行)

一个调度是合法的,如果同一时间没发生两个不同事务的锁冲突。(mysql需要保证并行事务不冲突)

因为每个事务T都是良构的,所以必定对应着一个解锁操作Unlock,事务T的解锁操作步骤在调度中的索引为St。

假设在调度中事务T1在事务T2之前执行,T1<<

如果一个调度包含的事物都是良构的且为两阶段的,那么该调度是可串行化的。

可能有人会问,为什么不给每个事务加排他锁来保证多事务执行的串行化呢?

是因为如果把读锁也定义为排他锁的话,会大大的降低并发读的效率,而查询操作在数据库的操作中占了很大的比例,所以mysql默认采用的可重复读的隔离级别,用两阶段协议和全场景覆盖的锁来保证执行结果的串行化,并没有采用全用排他锁来保证串行化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值