数据库并发事务详解

本章将从数据库事务的基本要素、并发事务带来的问题、数据库事务的隔离级别、封锁技术方面来进行详细解读。

 一、数据库事务正确执行的四个基本要素(事务的四个属性)

 当事务处理系统创建事务时,将确保事务有某些特性。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的特性。这些特性称为ACID特性。 ACID就是:原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily)。 
1、原子性 (Atomicity ) 
    原子性属性用于标识事务是否完全地完成,一个事务的任何更新要在系统上完全完成,如果由于某种原因出错,事务不能完成它的全部任务,系统将返回到事务开始前的状态。 
让我们再看一下银行转帐的例子。如果在转帐的过程中出现错误,整个事务将会回滚。只有当事务中的所有部分都成功执行了,才将事务写入磁盘并使变化 永久化。为了提供回滚或者撤消未提交的变化的能力,许多数据源采用日志机制。例如,SQL Server使用一个预写事务日志,在将数据应用于(或提交到)实际数据页面前,先写在事务日志上。但是,其他一些数据源不是关系型数据库管理系统 (RDBMS),它们管理未提交事务的方式完全不同。只要事务回滚时,数据源可以撤消所有未提交的改变,那么这种技术应该可用于管理事务。 
2、一致性( Consistency ) 
    事务在系统完整性中实施一致性,这通过保证系统的任何事务最后都处于有效状态来实现。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。因为事务开 
始时系统处于一致状态,所以现在系统仍然处于一致状态。 再让我们回头看一下银行转帐的例子,在帐户转换和资金转移前,帐户处于有效状态。如果事务成功地完成,并且提交事务,则帐户处于新的有效的状态。如果事务出错,终止后,帐户返回到原先的有效状态。 
记住,事务不负责实施数据完整性,而仅仅负责在事务提交或终止以后确保数据返回到一致状态。理解数据完整性规则并写代码实现完整性的重任通常落在 开发者肩上,他们根据业务要求进行设计。 当许多用户同时使用和修改同样的数据时,事务必须保持其数据的完整性和一致性。因此我们进一步研究A C I D特性中的下一个特性:隔离性。 
3、隔离性 ( Isolation) 
    在隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在 系统中认为只有该事务在使用系统。 这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。重要的是,在隔离状态执行事务, 系统的状态有可能是不一致的,在结束事务前,应确保系统处于一致状态。但是在每个单独的事务中,系统的状态可能会发生变化。如果事务不是在隔离状态运行, 它就可能从系统中访问数据,而系统可能处于不一致状态。通过提供事务隔离,可以阻止这类事件的发生。在银行的示例中,这意味着在这个系统内,其他过程和事 务在我们的事务完成前看不到我们的事务引起的任何变化,这对于终止的情况非常重要。如果有另一个过程根据帐户余额进行相应处理,而它在我们的事务完成前就 能看到它造成的变化,那么这个过程的决策可能 
建立在错误的数据之上,因为我们的事务可能终止。这就是说明了为什么事务产生的变化,直到事务完成,才对系统的其他部分可见。隔离性不仅仅保 证多个事务不能同时修改相同数据,而且能够保证事务操作产生的变化直到变化被提交或终止时才能对另一个事务可见,并发的事务彼此之间毫无影响。这就意味着 所有要求修改或读取的数据已经被锁定在事务中,直到事务完成才能释放。大多数数据库,例如SQL Server以及其他的RDBMS,通过使用锁定来实现隔离,事务中涉及的各个数据项或数据集使用锁定来防止并发访问。 
4、持久性 (Durabilily) 
    持久性意味着一旦事务执行成功,在系统中产生的所有变化将是永久的。应该存在一些检查点防止在系统失败时丢失信息。甚至硬件本身失败,系统的状态仍能通过在日志中记录事务完成的任务进行重建。持久性的概念允许开发者认为不管系统以后发生了什么变化,完 
成的事务是系统永久的部分。 在银行的例子中,资金的转移是永久的,一直保持在系统中。这听起来似乎简单,但这,依赖于将数据写入磁盘,特别需要指出的是,在事务完全完成并提交后才写 入磁盘的。 所有这些事务特性,不管其内部如何关联,仅仅是保证从事务开始到事务完成,不管事务成功与否,都能正确地管理事务涉及的数据 ,当事务处理系统创建事务 时,将确保事务有某些特性。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的特性。 

二、并发事务带来的问题

当多个用户同时访问数据库时会出现如同多线程对变量进行修改时的类似问题。并发事务的主要问题有四个:

1、更新丢失(Lost update) 
       两个事务T1和T2读入同一个数据并修改,T2提交的结果覆盖了T1提交的结果,导致T1的修改被丢失。 
2、脏读(Dirty Reads) 
       事务T1对数据进行修改,但是还没有提交时,事务T2读取数据进行修改,此时T2读取的是T1修改了的值。但是突然由于某种原因T1进行了回滚,这时候数据恢复了原来的值,而T2取得的数据依然是T1修改的值,这就导致了数据库中的值与事务获取的值不同的现象。也就是读到了不正确的值,这就叫脏读。

       比如张三工资为5000元,事务A将他的工资改为8000元,在事务A还未提交时,事务B正在读取张三的工资,读取的值为8000.这时候突然由于事务A发生了异常进行了回滚,张三的工资恢复成了5000元,而事务B读取的工资却是8000元,读取的值与数据库中的值不同,这就是脏读。
3、非重复读(Non-repeatable Reads) 
      是指在一个事务内,多次读取同一数据。在这个事务还没结束时,另外一个事务也访问该同一数据,并对该数据进行了修改。此时第一个事务再去读此数据时读到的结果与之前的结果不同。这就导致了在一个事务内两次相同的查询读到的数据是不一样的,因此称为是不可重复读。

      比如:在事务A中读到的张三的工资是5000元,操作还没有完成,事务还没提交。与此同时,事务B把张三的工资改为了8000,并提交了事务。随后,在事务A中,再次读取张三的工资,此时工资变为8000元。在A事务这一个事务内前后两次读取的结果不一致,导致了不可重复读。
4、幻读(Phantom Reads) 
    例如:目前工资为5000元的员工有10个人,事务A读取所有工资为5000元的员工的人数为10人。此时事务B插入一条工资也为5000的记录。这时,事务A再次读取工资为5000元的员工,记录为11人。此时产生了幻读。

     不可重复读和幻读的情况很类似,但是不可重复读的重点是修改:同样条件下,你读取过的数据,再次读取出来发现值不一样了。

     幻读的重点在于新增或者删除:同样条件下,第一次和第二次读出来的记录数不一样。

     避免不一致的方法和技术就是进行并发控制。最常用的就是封锁技术。封锁技术的缺点是会造成死锁和性能下降。为了兼顾并发效率与异常控制,定义了4中隔离级别。接下来将介绍隔离级别。

三、数据库事务的隔离级别

1、Read uncommitted(读未提交数据):

       如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

        避免了更新丢失,却可能出现脏读、不可重复读、幻读的情况。

2、Read committed(读已提交数据):

       读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

       该隔离级别避免了脏读,但是却可能出现不可重复读、幻读的情况。

3、Repeatable read(可重复读)

       读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

       避免了不可重复读取和脏读,但是有时可能出现幻读。这中隔离级别可以通过“共享读锁”和“排他写锁”实现。

这是MYSQL默认的隔离级别
4、Serializable(可串行化)

       提供严格的事务隔离。它要求事务串行化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务串行化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

       串行化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。


        隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。
Mysql的默认隔离级别就是可重复读取

四、MYSQL事务控制语句

        BEGIN或者START TRANSACTION:显示的开启一个事务。

        COMMIT:提交事务,并使已对数据库进行的所有修改称为永久性的。

        ROLLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。

五、数据库的锁机制

        按锁类型划分,可分为共享锁排他锁

        按锁的粒度划分,可分为表级锁行级锁页级锁

        按使用机制划分,可分为乐观锁悲观锁

1、按锁类型划分,可分为共享锁排他锁

    共享锁(也叫写锁、S锁):多个事务可封锁一个共享页;任何事务都不能修改该页;通常是该页读取完毕,S锁立即被释放。在执行select语句的时候需要给操作对象(表或者一些记录  )加上共享锁,但加锁之前需要检查是否有排他锁,如果没有,则可以加共享锁(一个对象上可以加n个共享锁),否则不行。共享锁通常在执行完select语句之后被释放,当然也有可能是在事务结束(包括正常结束和异常结束)的时候被释放,主要取决于数据库所设置的事务隔离级别。

    排他锁(也叫写锁、X锁):仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该锁页进行访问;X锁一直到事务结束才能被释放。执行insert、update、delete语句的时候需要给操作的对象加排他锁,在加排他锁之前必须确认该对象上没有其他任何锁,一旦加上排他锁之后,就不能再给这个对象加其他任何锁。排他锁的释放通常是在事务结束的时候(当然也有例外,就是在数据库事务隔离级别被设置成Read Uncommitted(读未提交数据)的时候,这种情况下排他锁会在执行完更新操作之后被释放,而不是在事务结束的时候)。

2、按锁的粒度划分,可分为表级锁行级锁页级锁    

       表级锁:直接锁定整张表,在锁定期间,其他进程无法对该表进行写操作。如果你是写锁,则其他进程读也不允许。特点是:开销小、加锁快,不会出现死锁。锁定粒度最大,发生锁冲突的概率最高,并发度最低。

        MYISAM存储引擎采用的就是表级锁。

       行级锁:仅对指定的记录进行加锁,这样其他进程还是可以对同一个表中的其他记录进行操作。特点:开销大,加锁慢,会出现死锁。锁定的粒度最小,发生锁冲突的概率最低,并发度也最高。

        InnoDB存储引擎既支持行级锁,也支持表级锁,但默认情况下是采用行级锁。

       页级锁:一次锁定相邻的一组记录。开销和加锁时间介于表级锁和行级锁之间;会出现死锁;锁定粒度也介于表级锁和行级锁之间,并发度一般。

3、按使用机制划分,可分为乐观锁悲观锁

  这两天要面试,偷个懒粘贴一下我书上的笔记吧,还请见谅(字有点丑,有时间我在把这部分具体的整理一下!)

  • 26
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
PostgreSQL 是一个功能强大的关系型数据库管理系统,在处理数据库事务并发控制方面有着很多特性和机制。下面是关于 PostgreSQL 数据库事务并发控制的一些重要信息: 1. 数据库事务事务是一组操作的逻辑单元,要么全部执行成功,要么全部回滚。在 PostgreSQL 中,事务的开始和结束通过 BEGIN 和 COMMIT 或 ROLLBACK 语句来定义。默认情况下,每个 SQL 语句都在单独的事务中执行,但你可以使用显式的 BEGIN 和 COMMIT 指令来控制事务的边界。 2. 并发控制:并发控制是指在多个用户同时访问数据库时,保证数据的一致性和正确性。PostgreSQL 使用多版本并发控制(MVCC)机制来实现并发控制。MVCC 使用了版本号(或时间戳)来跟踪事务的可见性和一致性。 3. 锁机制:PostgreSQL 使用锁来控制并发访问。锁可以对表、行或其他数据库对象进行加锁,以防止其他事务对其进行修改或访问。锁分为共享锁和排它锁,用于控制读取和写入操作之间的冲突。 4. 事务隔离级别:PostgreSQL 支持四种事务隔离级别,分别是读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。这些隔离级别提供了不同的并发控制策略,可以根据应用程序的需求进行配置。 5. 并发控制配置:PostgreSQL 提供了多种配置选项来调整并发控制的性能和行为。你可以通过修改配置文件或使用 ALTER SYSTEM 命令来更改这些选项。一些常见的配置选项包括 max_connections(最大连接数)、max_locks_per_transaction(每个事务最大锁数)和deadlock_timeout(死锁超时时间)等。 总而言之,PostgreSQL 提供了强大的数据库事务并发控制机制,通过锁机制、MVCC 以及事务隔离级别来处理并发操作和保证数据的一致性。这些特性使得 PostgreSQL 成为处理高并发场景下数据操作的理想选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值