精华内容
下载资源
问答
  • 数据库事务

    万次阅读 2019-12-16 10:46:25
    事务: 一组逻辑操作单元,使数据从一种状态变换到另一种状态。...要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单...
    事务:

    一组逻辑操作单元,使数据从一种状态变换到另一种状态。

    事务处理:

    保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。

    为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

    事务的ACID属性

    1. 原子性(Atomicity)
      原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
    2. 一致性(Consistency)
      事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
    3. 隔离性(Isolation)
      事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    4. 持久性(Durability)
      持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

    数据库的并发问题

    • 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
      • 脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容就是临时且无效的。
      • 不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了。
      • 幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 再次读取同一个表, 就会多出几行。
    • 数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题。
    • 一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。

    四种隔离级别

    隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
    未提交读(Read uncommitted)可能可能可能
    已提交读(Read committed)不可能可能可能
    可重复读(Repeatable read)不可能不可能可能
    可串行化(Serializable )不可能不可能不可能

    1. 声明配置文件

    jdbc.properties
    user=root
    password=00000000
    url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
    driverClass=com.mysql.jdbc.Driver
    

    2. 工具类

    JDBCUtils.java
    public class JDBCUtils {
        //获取数据库的连接
        public static Connection getConnection() throws Exception {
            //1.读取配置文件中的4个基本信息
            InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            String url = properties.getProperty("url");
            String driverClass = properties.getProperty("driverClass");
            //2.加载驱动
            Class.forName(driverClass);
            //3.获取连接
            return DriverManager.getConnection(url, user, password);
        }
        //关闭连接和Statement的操作
        public static void closeResource(Connection connection, Statement statement) {
            try {
                if(statement != null)
                    statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //关闭资源操作
        public static void closeResource(Connection connection, Statement statement, ResultSet resultSet) {
            try {
                if(statement != null)
                    statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(resultSet != null)
                    resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

    3. 通用的增删改方法(考虑事务)

    public int update(Connection connection, String sql, Object... args) {
        PreparedStatement preparedStatement = null;
        try {
            //1.预编译sql语句,返回PreparedStatement的实例
            preparedStatement = connection.prepareStatement(sql);
            //2.填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            //3.执行操作
            return preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //4.资源的关闭
            JDBCUtils.closeResource(null, preparedStatement);
        }
        return 0;
    }
    
    3.1 user_table表结构

    user_table表结构

    3.2 测试代码

    用户AA向用户BB转账100

    @Test
    public void testUpdateWithTx() {
        Connection connection = null;
        try {
            connection = JDBCUtils.getConnection();
            System.out.println(connection.getAutoCommit()); //true
            //1.取消数据的自动提交
            connection.setAutoCommit(false);
            String sql1 = "update user_table set balance = balance - 100 where user = ?";
            update(connection, sql1, "AA");
            //模拟网络异常
            System.out.println(10 / 0);
            String sql2 = "update user_table set balance = balance + 100 where user = ?";
            update(connection, sql2, "BB");
            System.out.println("转账成功");
            //2.提交数据
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            //3.回滚数据
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            JDBCUtils.closeResource(connection, null);
        }
    }
    

    4. 通用的查询方法(考虑事务)

    public <T> List<T> getForList(Connection connection, Class<T> clazz, String sql, Object... args) {
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();
            //获取结果集的元数据:ResultSetMetaData
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            //通过ResultSetMetaData获取结果集中的列数
            int columnCount = resultSetMetaData.getColumnCount();
            //创建集合对象
            ArrayList<T> list = new ArrayList<>();
            while (resultSet.next()) {
                T instance = clazz.newInstance();
                //处理结果集一行数据中的每一个列:给instance对象指定的属性赋值
                for (int i = 0; i < columnCount; i++) {
                    //获取列值
                    Object columnValue = resultSet.getObject(i + 1);
                    //获取每个列的列名
                    String columnLabel = resultSetMetaData.getColumnLabel(i + 1);
                    //给customer对象指定的columnName属性,赋值为columnValue(通过反射)
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(instance, columnValue);
                }
                list.add(instance);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(null, preparedStatement, resultSet);
        }
        return null;
    }
    
    4.1 User类
    User.java
    public class User {
        private String user;
        private String password;
        private int balance;
    
        public User() {
            super();
        }
    
        public User(String user, String password, int balance) {
            super();
            this.user = user;
            this.password = password;
            this.balance = balance;
        }
    
        public String getUser() {
            return user;
        }
    
        public void setUser(String user) {
            this.user = user;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public int getBalance() {
            return balance;
        }
    
        public void setBalance(int balance) {
            this.balance = balance;
        }
    
        @Override
        public String toString() {
            return "User [user=" + user + ", password=" + password + ", balance=" + balance + "]";
        }
    }
    
    4.2 user_table表结构

    user_table表结构

    4.3 测试代码
    @Test
    public void testTransactionSelect() throws Exception{
        Connection connection = JDBCUtils.getConnection();
        //获取当前连接的隔离级别
        System.out.println(connection.getTransactionIsolation()); //4
        //设置当前连接的隔离级别:
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
        System.out.println(connection.getTransactionIsolation()); //2
        //取消自动提交数据
        connection.setAutoCommit(false);
        String sql = "select user,password,balance from user_table where user = ?";
        List<User> user = getForList(connection, User.class, sql, "CC");
        user.forEach(System.out::println); //User [user=CC, password=abcd, balance=2000]
    }
    
    @Test
    public void testTransactionUpdate() throws Exception{
        Connection connection = JDBCUtils.getConnection();
        //取消自动提交数据
        connection.setAutoCommit(false);
        String sql = "update user_table set balance = ? where user = ?";
        update(connection, sql, 5000,"CC");
        Thread.sleep(15000);
        System.out.println("修改结束");
    }
    
    展开全文
  • 使用Spring框架实现数据库事务处理

    千次阅读 2020-03-02 21:20:45
    本文主要讨论在Spring框架中如何使用数据库事务处理更新数据库数据。通过本课的学习,可以达到如下目标。 ● 了解JDBC对数据库事务处理的支持 ● 掌握在Spring框架中使用事务处理的技术 事务处理对数据库来说,是...

    企业级应用系统在更新数据库数据时,一般都采用数据库事务处理,以确保数据库数据的一致性。本文主要讨论在Spring框架中如何使用数据库事务处理更新数据库数据。通过本课的学习,可以达到如下目标。

    ● 了解JDBC对数据库事务处理的支持

    ● 掌握在Spring框架中使用事务处理的技术

    事务处理对数据库来说,是对数据库的一系列SQL语句操作,这些操作被组织为一个事务。事务具有原子性,即事物中的操作要么全部执行,要么全部不执行。若事务中的SQL语句在执行过程中发生错误,事务需要对已经执行的SQL语句进行回滚操作,撤销先前对数据库的操作,防止数据库出现错误状态。

    例如,在课程案例mooc数据库中,一个业务是学生购买课程,购买课程业务步骤包括更新teacher表,记录老师的收入,同时student_course表增加一条购买记录,更新student表的余额字段。上述业务步骤需要全部执行完毕,才能反映出学生购买课程的正确状态。如果因意外情况,上述操作仅成功执行了部分SQL语句,其它语句没有执行或执行失败,就会造成学生购买课程这个业务记录不完整,数据库处于数据错乱状态。若利用数据库事务技术执行上述操作,当发生上述情况时,数据库系统会将先前执行的SQL语句撤销,将数据库回滚到事务执行前状态。

     

    1、JDBC对数据库事务处理的支持

    JDBC本身就提供了对数据库事务处理的支持,使用java.sql.Connection对象完成事务的提交。使用Connection提交数据库事务处理代码如下。

     

    Connection类的setAutoCommit方法用于设置JDBC提交SQL语句的方式。设置为ture时,JDBC自动提交SQL语句,JDBC提交SQL语句的方式默认为true。设置为false时,SQL语句的提交由应用程序负责,应用程序必须调用commit方法,同时要在执行SQL语句异常处理块中调用rollback方法,对异常发生前进行的数据库进行回滚操作。

    在企业级应用中,事务一般是并发执行的,当事务并发执行时,就会发生数据库数据同步的问题,具体问题可分为下面四种类型。

    (1)脏读:一个数据库事务在更新数据的过程中,数据是保存在内存中的,只有调用commit方法,更新的数据才最终写到数据库中。如果一个事务使用了另一个事务更新但没保存的数据,这个数据就称为脏数据,事务读取这个数据就称为脏读。

    (2)不可重复读:在同一事务中,两次读取同一记录,读取的记录内容却不相同。例如,事务A第一次读取了一条记录,同时事务B更新并提交了该条记录,事务A第二次读取该条记录时,当前读取的记录内容和第一次读取的记录内容不相同。

    (3)幻读:当事务A对表中的所有记录进行了修改,同时事务B又在表中插入了一条新的记录。A事务在后续对该表操作时,就会发现表中还存在没有修改的记录,就好象发生了幻觉一样。

    (4)丢失更新:当事务A和事务B对同一数据进行修改时,就会发生丢失更新的问题。例如,B事务对m记录进行了修改,A事务在修改m记录时发生异常并回滚,就会将B事务对m记录的修改覆盖掉。

    为了解决上面提到的事务并发问题,JDBC定义了五种事务隔离级别来解决来解决这些并发导致的问题。

    表1 JDBC提供的事务隔离级别说明

     

    表中隔离级别从上到下依次增高,最高级别是TRANSACTION_SERIALIZABLE,它通过强制事务串行执行(不是并行),避免了事务并发执行导致发生的数据同步问题。出于应用程序访问数据库性能的考虑,一般设置隔离级别为TRANSACTION_READ_COMMITTED。

     

    2、在Spring框架中调用事务处理

    下面给出具体执行事务处理的案例程序。案例程序的数据源采用mooc数据库,mooc数据库的结构以及本案例中没有列出的代码详见《Spring使用JDBC访问MySQL数据库》一文。

    让Spring框架开始执行一个数据库事务时,需要分成三步走。第一步配置数据源DataSource;第二步声明事务管理TransactionManager类;第三步定义可以执行事务的DAO类。

    第一步:配置数据源DataSource

    需要让Spring框架知道数据库的位置及其连接方式,这个工作由DataSource完成。Spring框架通过DataSource连接数据库,DataSource既可以在Spring框架的配置文件中配置,也可以放在Bean类中配置。下面是在Spring配置文件中配置数据源的代码。

     

    配置语句定义了MySQL数据库的URL地址、访问账户及访问密码。

    第二步:声明事务管理TransactionManager

    Spring 框架提供了PlatformTransactionManager作为事务管理类的顶层接口,声明了初始化事务、提交事务、回滚事务等接口。接口实现由具体的数据库驱动类实现。具体包括DataSourceTransactionManager、HibernateTransactionManager等实现类。本文主要用DataSourceTransactionManager来实现事务的管理。在Spring框架配置文件中配置DataSourceTransactionManager类。

     

    声明DataSourceTransactionManager类,需要传入之前已声明的DataSource数据源。

    第三步:定义可以执行事务的DAO类

    DAO提供了应用程序访问数据源必要的接口和方法,接口和方法的具体实现细节,程序并不需要了解。DAO的具体细节详见《Spring使用JDBC访问MySQL数据库》一文。

     

    CourseTransactio类实现了CourseDao接口,CourseDao是访问mooc数据库的顶层接口,接口提供了mooc数据库表的增删改查操作。CourseTransactio主要实现了CourseDao类的buyCourse,实现学生购买课程事务。购买课程事务涉及到更新teacher表,在student_course表增加一条购买记录,更新student表的余额字段数据库操作,这些操作需要进行连续处理,中间不能中断出错,如果出错则需要做回滚处理。 因此,buyCourse方法采用数据库事务进行处理。

    事务处理从TransactionDefinition开始,前面我们谈到了事务的隔离级别,TransactionDefinition就是用来定义事务隔离级别的。DefaultTransactionDefinition表示使用数据库的默认隔离级别,对大部分数据库而言,默认隔离级别是TRANSACTION_READ_COMMITTED。

    当TransactionDefinition 创建后,可以通过调用 getTransaction方法开始事务,该方法会返回 TransactionStatus 的一个实例。 TransactionStatus 用于追踪当前的事务状态,如果后面的SQL语句都运行成功,可以使用 TransactionManager 的 commit() 方法来提交这个事务,否则使用 rollback() 方法来回滚整个操作。

    完整的配置文件代码。

     

    学生实体类代码。

     

     

    老师实体类代码。

     

    student表映射到学生实体类。

     

    teacher表映射到老师实体类。

     

    测试类代码。

     

    课程小结

    (1)事务处理对数据库来说,是对数据库的一系列SQL语句操作,这些操作被组织为一个事务。事务具有原子性,即事物中的操作要么全部执行,要么全部不执行。若事务中的SQL语句在执行过程中发生错误时,事务需要对已经执行的SQL语句进行回滚操作,撤销先前对数据库的操作,防止数据库出现错误状态。

    (2)让Spring框架开始执行一个数据库事务时,需要分成三步走。第一步配置数据源DataSource;第二步声明事务管理TransactionManager类;第三步定义可以执行事务的DAO类。

    展开全文
  • 数据库事务处理

    2020-06-02 22:55:57
    数据库事务是一个逻辑上的划分,的时候并不是很明显,它可以是一个操作步骤也可以是多个操作步骤。我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在...

    1、简介

           数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

           数据库事务是一个逻辑上的划分,有的时候并不是很明显,它可以是一个操作步骤也可以是多个操作步骤。我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在自己的终端可以预览变化,直到全部修改完成,并经过检查确认无误后,一次性提交并写入数据库,在提交之前,必要的话所做的修改都可以取消。提交之后,就不能撤销,提交成功后其他用户才可以通过查询浏览数据的变化。

           经典案例:银行转账,第一步骤从第一个账户划出款项,第二步骤将款项存入第二个账户。在这个过程中,两个环节是关联的。第一个账户划出款项必须保证正确的存入第二个账户,如果第二个环节没有完成,整个的过程都应该取消,否则就会发生丢失款项的问题。整个交易过程,可以看作是一个事物,成功则全部成功,失败则需要全部撤消,这样可以避免当操作的中间环节出现问题时,产生数据不一致的问题。

     

    2、性质(ACID)

    • 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
    • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
    • 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
    • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

           事务的ACID特性是由关系数据库系统(DBMS)来实现的,DBMS采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所作的更新,如果某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使得数据库同滚到执行事务前的初始状态。

           对于事务的隔离性,DBMS是采用锁机制来实现的。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。

     

    3、作用

    • 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
    • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

     

    4、数据库事务处理相关命令

    进行的操作

    命令

    查看存储引擎

    SHOW CREATE TABLE 表名;

    更改引擎

    ALTER TABLE 表名 ENGINE=新引擎名;

    回滚

    ROLLBACK;

    声明事务开始

    BEIGIN;

    事务提交

    COMMIT;

    查询自动提交功能状态

    SELECT @@AUTOCOMMIT;

    设置自动提交功能

    SET AUTOCOMMIT=0或1;

    设置分离水平

    SET SESSION TRANSACTION ISOLATION LEVEL 分离水平;

     

    5、存储引擎

           MySQL数据库的存储引擎是可以选择改变和替换的(可替换存储引擎构架,Pluggable Storage Engine Architecture)。MySQL主要有8种存储引擎:

    存储引擎

    特征

    MyISAM

    高速引擎,不支持事务处理

    InnoDB

    支持行锁定以及事务处理,速度比MyISAM稍慢

    ISAM

    MyISAM的前身

    MERGE

    将多个MyISAM类型的表作为一个表来处理的引擎

    MEMORY,HEAP

    只在内存上保存数据

    Falcon

    一种新的存储引擎,支持事务处理

    ARCHIVE

    将数据压缩后保存(只能支持INSERT/SELECT操作

    CSV

    以CSV形式保存数据(应用于跨平台数据交换)

     

    6、事务处理

           之前讲到,事务处理是一毁全毁,因此事务中任意一个任务或指令失败,整个事务都将失败。那是怎么实现的呢?方法是时间中多个任务全部成功,则任务成功结束,并且会进行提交(COMMIT),如果任何一件任务失败,则强制回滚(ROLLBACK)到初始状态。

           事务处理涉及到三个最重要的命令:BEGIN,ROLLBACK,COMMIT,分别表示声明事务开始,回滚,确认提交

    (1)回滚

    事务在BEGIN之后但还没COMMIT的时候可以用ROLLBACK回滚到BEGIN之前的数据,而如果COMMIT提交之后则不能用ROLLBACK回滚到原来的数据。

    (2)自动提交

    当搜索引擎为MyISAM时,因为不支持事务处理,因此命令一旦执行,就一定会提交,这种默认的提交方式被称为自动提交。

           而当搜索引擎设置为InnoDB时,可以设置自动提交功能是否开启,当自动提交功能为ON时,命令执行就会提交(COMMIT),而自动提交设置为OFF 时,必须执行COMMIT才提交,可以使用ROLLBACK进行回滚。

    查询当前自动提交功能状态:

    SELECT @@AUTOCOMMIT;
    

    设置自动提交功能:

    SET AUTOCOMMIT=0或1;
    

    (3)部分回滚

           直接ROLLBACK会回滚到BEGIN开始之前的地方,而通过SAVEPOINT可以保存一个点,通过ROLLBACK TO SAVEPOINT就可以回滚到保存点了,也就实现了“想去哪就去了哪”。

    部分回滚主要有两个步骤:

    ①保存点

    SAVEPOINT 保存点名;
    

    ②回滚到保存点

    ROLLBACK TO SAVEPOINT 保存点名;
    

    (4)不能事务处理的命令(直接提交)

           大部分命令都可以通过事务处理(BEGIN -ROLLBACK- COMMIT)进行操作,但是:

    • DROP DATABASE;
    • DROP TABLE;
    • DROP;
    • ALTER TABLE

    不能通过事务处理,会直接COMMIT;

     

    7、锁定与事务处理

    (1)锁定

    (a)锁定的分类

           锁定分为共享锁定(Shared Lock)和排他锁定(Exclusive Lock):

    • 共享锁定是将对象数据变为只读形式,不能进行更新,所以也称为读取锁定;
    • 排他锁定是当执行INSERT/UPDATE/DELETE的时候,其它事务不能读取该数据,因此也称为写入锁定。

    (b)锁定的粒度

           锁定对象的大小是锁定的粒度,有三种粒度:

    • 记录
    • 数据库

    (2)事务处理的分离水平

           需要使用锁定来有效解决事务冲突的情况,但是锁定也会使性能下降(因为别人无法访问),因此频繁锁定不一定合理,数据库中,使用分离水平来表示事务处理之间的影响程度。

           事务处理的分离水平对应的数据整合情况:

    分离水平

    非提交读取

    不可重复读取

    幻象读取

    READ UNCOMMITED

    READ COMMITED

    ×

    REPEATABLE READ

    ×

    ×

    SERIALIZABLE

    ×

    ×

    ×

    设置分离水平可以使用命令:

    SET SESSION TRANSACTION ISOLATION LEVEL 分离水平;
    

    (a)非提交读取

           非提交读取指的是别的事务能够读取到还没有提交的更新数据,只发生在分离水平为READ UNCOMMITED的情况下。

           因为对事务处理的读取没有任何限制,所以一般不推荐使用。

    (b)不可重复读取

           不可重复读取是指在某事务处理过程中对数据进行读取,由于该事务更新操作导致多次读取数据时发生了改变。

           不可重复读取发生在READ COMMITED 一下的分离水平。

    (c)幻象读取

           幻象读取指的是,在某事物处理数据过程中对数据多次读取,由于该事务的插入/删除操作而导致在多次读取过程中读取到不存在或者消失的数据。

           当设置分离水平为SERIALIZABLE时,可以消除幻象读取。

    (3)死锁 Dead Lock

           死锁指的是两个事务互相对待对方释放锁定,则永远也不可能接触锁定的状态。

     

    参考:https://blog.csdn.net/moxigandashu/article/details/62046030

     

    展开全文
  • 数据库事务介绍

    2016-06-12 16:23:57
    数据库事务介绍数据库事务主要类型 本地事务(JDBC):单数据源 全局事务(JTA):全局事务的实现通常是采用二次提交方式。多数据源 数据库事务概念:所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态...

    数据库事务介绍


    数据库事务主要类型

     本地事务(JDBC):单数据源
     全局事务(JTA):全局事务的实现通常是采用二次提交方式。多数据源
    

    数据库事务概念:所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态

    事务的ACID属性:

    1. 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 
    2. 一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
    3. 隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。(简单理解:上锁资源独享)
    4. 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
    

    对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

    脏读: 对于两个 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
    不可重复读: 对于两个事务 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
    幻读: 对于两个事务 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
    

    数据库事务的隔离性:

    数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.
    一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 
    不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱
    

    数据库隔离级别:

    可串行化:(Serializable)最安全,但是效率最低
    可重复读:(Repeatable read)有幻读可能(推荐)mysql 默认设置
    读已提交:(Read committed)有不可重复读、幻读(推荐)oracle默认设置
    读未提交:(Read uncommitted)脏读、不可重复读、幻读。安全性最差,效率最高
    

    锁(悲观锁、乐观锁)

    锁机制主要是为了解决并发性问题的

    悲观锁:

    通常是由数据库机制实现的,在整个过程中把数据锁住(查询时),
    只要事务不释放(提交/回滚)那么任何用户都不能查看或修改。
    

    乐观锁

    大多数的使用是采用数据版本的方式(version)实现,
    一般在数据库中加入一个version字段在读取数据的时候将version读取出来,
    在保存数据的时候判断version的值是否小于数据库中的version值,
    如果小于不予更新,否则给予更新。
    
    展开全文
  • 1.事务(Transaction)是并发控制的基本单位。 所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。...事务数据库维护数据一致性的单位,在每个事务结束时,...
  • 数据库事务管理

    2014-09-28 16:16:31
     不管你直接采用JDBC进行数据库事务操作,还是使用基于Spring或EJB的声明式事务功能进行事务管理,它们最终都是使用底层数据库的事务管理功能完成最终任务的。数据库事务拥有许多语义概念,它们是你进行事务编程和...
  • 事务对于数据库来说是,是对sql语句的一系列操作,这些操作被组织成为一个事务。...使用Connection提交数据库事务处理如下: 发现里面一个方法叫setAutoCommit(),设置为true时,就是自动提交sql.
  • Django 数据库事务

    万次阅读 2016-03-30 16:07:46
    管理数据库事务Django框架提供了好几种方式来控制和管理数据库事务。(以下Django框架会简化为Django,读者可自行脑补框架两字)Django框架默认的事务行为自动提交作为Django默认的事务行为,它表现形式为:每次...
  • 说说数据库事务

    2018-11-10 11:22:38
    数据库事务必须同时满足 4 个特性 ( ACID )。 特性 说明 原子性 Atomic 表示组成一个事务的多次数据库操作是一个不可分割的原子单元,只有所有的操作都执行成功,才提交整个事务 。 事务中的任何一次...
  • 不管你直接采用JDBC进行数据库事务操作,还是使用基于Spring或EJB的声明式事务功能进行事务管理,它们最终都是使用底层数据库的事务管理功能完成最终任务的。数据库事务拥有许多语义概念,它们是你进行事务编程和...
  • 因为最近在导师手下做一个微服务和分布式事务相关的课题项目,作为必要的前置准备,需要加深下对单机事务的认识并理解其实现原理。这篇文章是在我给组内的小伙伴分享的PPT的基础上改动而成,旨在帮助大家建立关于事务的...
  • 数据库事务系列-事务模型基础

    千次阅读 2017-08-09 17:00:06
    数据库事务系列-事务模型基础
  • 数据库事务的隔离级别

    千次阅读 2016-12-03 12:28:00
    由于事务的ACID特性,即Atomicity、Consistency、Isolation、Durability(原子性、一致性、隔离性、持续性),那么对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会...
  • 数据库事务的概念 数据并发的问题 数据库锁机制 事务隔离级别 JDBC对事务的支持概述在使用Spring开发应用时,Spring的事务管理可能是被使用最多、应用最广的功能。 Spring不但提供了和底层事务源无关的事务抽象,还...
  • Android数据库使用事务-Transcation

    千次阅读 2015-09-19 20:16:04
    一、背景:前段时间开发一个项目,需要使用Android数据库做本地缓存,当时从服务断获取的数据几千条,把数据插入到了数据库。 如果不使用事务,需要较长时间才能完成,效率很...使用事务-Transcation是很有必要的。
  • 数据库事务的概念

    2017-02-15 17:49:24
     事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换成另一种状态。    事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)...
  • 简述数据库事务并发机制

    万次阅读 多人点赞 2017-04-21 11:17:34
    事务是最小的逻辑执行单元,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务具有四个重要特征,即原子性、一致性、隔离性和持久性。本文首先叙述了数据库事务...
  • 数据库事务 Java 本身同样对数据库事务处理作了支持,事务针对上篇博客 JDBC 连接数据库是涉及到的 Connection 对象,获取的 Connection 对象默认是自动 commit(提交) 对数据库做的修改的,由此当事务不能完整执行...
  • [Java]Spring数据库事务基础知识

    千次阅读 2015-10-13 16:54:40
    要深入了解Spring的事务管理和配置,有必要先对数据库事务的基础知识进行学习。 何为数据库事务 “一荣俱荣,一损俱损”这句话很能体现事务的思想,很多复杂的事物要分步进行,但它们组成一个整体,要么整体生效,...
  • CMU Advanced DB 课程笔记#2:数据库工作负载和数据库事务模型CMU Advanced DB 课程笔记#2:数据库工作负载和数据库事务模型数据库工作负载:数据库事务(Transaction简称为Txn):Transaction Model:Flat Txns:...
  • 1. 抛出受查异常XXXException,事务会回滚。2. 抛出运行时异常NullPointerException,事务会回滚。3. Quartz中,execute直接调用加了@Transactional方法,可以回滚;间接调用,不会回滚。4. 异步任务中,execute...
  • 数据库事务&存储过程

    千次阅读 2019-02-28 15:58:24
    一、【事务概念】 事务(Transaction)是指构成单一逻辑...2,同时,该事务数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行。 二、【事务举例】 用一个常用的“A 账户向 B 账户汇钱”的例子来说...
  • 数据库事务管理原理

    千次阅读 2016-04-06 15:15:13
    数据库事务 数据库是一个共享资源,可以提供多个用户使用。这些用户程序可以一个一个地串行执行,每个时刻只有一个用户程序运行,执行对数据库的存取,其他用户程序必须等到这个用户程序结束以后方能对...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 136,410
精华内容 54,564
关键字:

是否有必要使用数据库事务