数据库事务知识点

一、ACID

  • 原子性( A ):事务是最小的单元,要么全部成功,要么全部回滚。
  • 一致性( C ):事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。事务前后保持处于一致的状态,不管在任何给定的时间并发事务有多少。一个事务是数据状态的切换,因此,如果事务并发对个,系统也必须串行执行这些事务操作。
  • 隔离性( I ):多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。
  • 持久性( D ):事务的结果不能丢失。

在并发环境下,事务的隔离性很难保证,从而引发并发一致性问题。

  • 脏读:T1修改了一个数据,未提交之前被T2读取到了。随后T1撤销了修改,T2读到了脏数据。
  • 不可重复读:T1读取->T2修改->T1再读。
  • 幻读:T1select count()->T2insert->T1数据不准确
  • 丢失更改 ::T1更改->T2更改 T1更改失效

对于简单的事务隔离性问题,我们可以通过设置事务隔开级别来保证数据一致性,通常通过@Transational注解来管理事务。其默认使用数据库引擎默认的隔离级别。

  • READ_UNCOMMITTED:未授权读取级别
    • 读事务允许其他读事务和写事务,未提交的写事务禁止其他写事务(但允许其他读事务)。可以防止丢失更改问题。
  • READ_COMMITTED:授权读取级别
    • 读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。可以防止丢失更改,脏读。
  • REPEATABLE_READ:可重复读取级别
    • 读事务禁止其他写事务(但允许其他读事务),未提交的写事务禁止其他读事务和写事务。 可以防止丢失更改,脏读,不可重复读。
  • SERIALIZABLE:序列化级别
    • 一个一个走,并行转串行。

数据库的事务隔离级别的实现通常是通过加锁或 undo log+MVCC实现。

以下原文链接

锁实现

  • 未提交读:一个update事务A只有在对数据修改时才加write lock,一旦写完马上释放write lock,即使事务A还没有提交。因此事务B在读取同一行时,才能读到事务A修改过的数据。

  • 提交读:一个update事务A只有在对数据修改时才加write lock,但直到事务A commit时才释放写锁。因此,同时进行的事务B希望读取同一行数据时,会被事务A的write lock堵塞,所以解决了脏读的问题。

  • 可重复读:这个隔离等级的条件下,除了执行提交读的写锁方式,还会在读取一行数据后,为这行数据添加read lock直至事务commit。例如,事务A读取ID=1这一行数据,然后为ID=1添加read lock。事务B同时希望update ID=1,此时获取写锁失败,因此在事务A执行完之前,没有其他任何事务可以对ID=1这一行做修改,因此解决了重复读的问题

虽然读写锁解决了Isolation问题,但锁会导致大量的堵塞,性能下降。某些时候会造成死锁,为了解决死锁,还要添加死锁探测机制,性能进一步下降,因此需要更高效的方式实现Isolation。

MVCC实现

MVCC实现
以上原文链接

发布了21 篇原创文章 · 获赞 24 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_30332665/article/details/105374874