MySQL事务

什么是事务

事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位(不可再分割),由一个有限的数据库操作序列构成(多个DML语句,select 语句不包含事务),要么全部成功,要么全部失败。

一组有限个操作的集合,要么全部成功,要么全部失败。

事务特性

事务应该具有四个属性:原子性、一致性、隔离性、持久性(ACID)

原子性(atomicity)一致性(consistency)隔离性(isolation)持久性(durability)

我们用一个银行转账的例子来说明。

特性解释:

  • 原子性(Atomicity):事务里的操作要么全部成功,要么全部失败回滚。就像一个不可分割的整体,不能只执行其中一部分操作。

例如,在银行转账操作中,从一个账号扣款和向另一个账号这两个操作必须一起完成,若其中一个操作失败,整个转账事务就会回滚。

  • 一致性(consistency):事务执行前后,数据库从一个一致性状态转变到另一个一致性状态。一致性是由原子性、隔离性和持久性共同保证的。

例如,在转账过程中,无论是否成功,所有账户的总金额应该保持不变。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不会被其他事务干扰,每个事务都感觉不到其他事务在并发执行。

例如,在多个用户同时进行转账操作时,每个用户的转账事务应该相互隔离,不会互相影响。

  • 持久性(Durability):事务一旦提交,它对数据库的改变就是永久性的,即便系统崩溃也不会丢失。

例如,当银行转账事务提交后,即使数据库服务突然断电,转账的结果也不会丢失。

package com.pgs.test;


import java.sql.*;

public class MySQLTransactionExample {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/testdemo";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "1234";


    public static void main(String[] args) {
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            //关闭自动提交事务
            conn.setAutoCommit(false);

            //创建示例表
            createAccountsTable(conn);
            //插入初始数据
            insertInitialData(conn);
            //模拟转账操作
            transferMoney(conn, 1, 2, 500);
            //提交事务
            conn.commit();
            System.out.println("转账成功!");
            //查询账户余额
            printAccountBalance(conn);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 关闭数据库连接
            if (conn != null) {
                try {
                    conn.setAutoCommit(true);
                    conn.close();
                    System.out.println("数据库连接已关闭。");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    // 打印账户余额
    private static void printAccountBalance(Connection conn) throws SQLException {
        String selectSQL = "SELECT id, balance FROM accounts";
        try (PreparedStatement preparedStatement = conn.prepareStatement(selectSQL);
             ResultSet resultSet = preparedStatement.executeQuery()) {
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                double balance = resultSet.getDouble("balance");
                System.out.printf("账户 ID: %d, 余额: %.2f%n", id, balance);
            }
        }
    }

    // 转账操作
    private static void transferMoney(Connection connection, int senderId, int receiverId, double amount) throws SQLException {
        // 从发送者账户扣款
        String deductSQL = "UPDATE accounts SET balance = balance - ? WHERE id = ?";
        try (PreparedStatement deductStatement = connection.prepareStatement(deductSQL)) {
            deductStatement.setDouble(1, amount);
            deductStatement.setInt(2, senderId);
            deductStatement.executeUpdate();
        }
        // 向接收者账户存款
        String depositSQL = "UPDATE accounts SET balance = balance + ? WHERE id = ?";
        try (PreparedStatement depositStatement = connection.prepareStatement(depositSQL)) {
            depositStatement.setDouble(1, amount);
            depositStatement.setInt(2, receiverId);
            depositStatement.executeUpdate();
        }
    }

    // 插入初始数据
    private static void insertInitialData(Connection conn) throws SQLException {
        String insertSQL = "INSERT INTO accounts (balance) VALUES (1000), (2000)";
        try (PreparedStatement preparedStatement = conn.prepareStatement(insertSQL)) {
            preparedStatement.executeUpdate();
        }
    }

    // 创建示例表
    private static void createAccountsTable(Connection conn) throws SQLException {
        String createTableSQL = "CREATE TABLE IF NOT EXISTS accounts (" +
                "id INT AUTO_INCREMENT PRIMARY KEY, " +
                "balance DECIMAL(10, 2))";
        try (PreparedStatement preparedStatement = conn.prepareStatement(createTableSQL)) {
            preparedStatement.executeUpdate();
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值