数据库中并发问题及解决办法(锁与数据库隔离级别)

数据库并发一致性问题

在并发环境下,事务的隔离性难以保障,就会出现很多并发一致性的问题
为方便表示,用“T”表示事务

  1. 丢失修改
    T1和T2都对一个数据进行修改,T1先修改,T2后修改,T2的修改覆盖掉了T1的修改,则使得T1对数据库数据的修改丢失。

  2. 读脏数据
    T1修改一个数据,T2紧接着读取到了这个数据,随后T1又回滚了此次操作,那么T2就读到了脏数据。

  3. 不可重复读
    T2读取了一个数据,T1对这个数据进行修改后,T2又在此读取这个数据,就会发现两次读取的结果不同。

  4. 幻影读
    T1要求读取某个范围的数据,T2在这个范围内插入了新的数据,T1再次读这个范围的数据就会和第一次读取的结果不同。

**结论:**这些并发中产生的问题破坏了事务特性中的隔离性,解决这种问题主要有两种方法,分别从并发控制和事务的隔离级别出发

1. 并发控制:像java语言一样,可使用锁来更好的控制并发问题
2. 事务隔离级别:使用数据库管理系统提供的数据库事务的隔离级别来控制并发问题

解决方法一:锁

在此使用MYSQL数据库为例分析
MYSQL中提供两种锁机制,分别为行锁和表锁
这里系统开销与并发程度是一对矛盾体:

  • 应该尽量只对需要使用的那部分资源加锁,而不是对所有资源(整张表)加锁,锁定的数据量越小,发生锁竞争的可能性就越小,系统的并发程度就会越高,在相同的时间内处理的业务也就更多;

  • 但是锁锁定的数据量越少,即锁的粒度越小,那么对于锁的各种操作(包括锁的检测、获取、释放等)会增加大量的系统开销,

  • 读写锁
    1.写锁(排它锁),简写为X锁
    2.读锁(共享锁),简写为S锁
    规定:一个事务对数据A添加了X锁,对A进行读取和更新,其他事务不能对A加任何锁
    一个事务对数据A添加了S锁,对A进行读取,其他事务可以对A进行读取,但是不能修改
    在这里插入图片描述
    意向锁
    意向锁(IX或IS锁)作用:可以更容易的支持多粒度加锁
    在原来的行锁和表锁存在下,事务每一次想要对表进行加锁,都需要检测其他事务是否对本表以及本表中的任意一行加了锁,这种检测是非常耗时的,那么引入了意向锁,表示一个事务想要对表中的某个数据行加锁(X锁或者S锁)

  • 1.一个事务在对某个数据行对象加S锁之前,必须要先获取本表的IS锁或者更强的锁(S锁、IX锁或者X锁

  • 2.一个事物在对某个数据行对象加X锁之前,必须获取表的IX锁

  • 通过意向锁,此事务只需检测其他事务是否对本表加了IX/IS/S/X锁,而不需要逐行检测。 因为在对数据行加锁之前,必须要获取到表的某个锁,反正若事务检测到本表被添加了锁,那么就证明本表中某个数据行被加锁(正在使用),就不再浪费时间去逐行检测。

在这里插入图片描述
IS与IX锁之间都是兼容的,因为他们只是表示想要对表加锁,并不是真正意义上的加锁
S锁只与S锁和IS锁兼容,也就是说事务想要对数据行加S锁,其他事务可以获得已经对表或者表中的行的S锁

解决方法二:事务的隔离级别

  • 未提交读(READ UNCOMMITTED):事务中的修改在没有提交之前对其他事务是可见的
  • 提交读(READ COMMITTED):一个事务只能读取已经提交的事务所做的修改。在没有提交之前对其他事务是不可见的。
  • 可重复读(REPEATABLE READ):保证在同一个事务中多次读取同样数据的结果是一样的。
  • 可串行化(SERIALIZABLE):强制事务串行执行,这个需要加锁实现。
    在这里插入图片描述
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值