数据库的事务
事务的四个基本特性(ACID)
原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个环节。
一致性(Consistency):事务必须使数据库从一个一致的状态转移到另一个一致的状态。
隔离性(Isolation):并发执行的事务之间不会互相影响。
持久性(Durability):一旦事务提交,它对数据库的改变就是永久性的,即使系统发生故障也不会丢失。
事务的隔离级别
为了处理并发事务,数据库系统提供了不同的事务隔离级别,包括:
- 读未提交(Read Uncommitted)
- 读已提交(Read Committed)
- 可重复读(Repeatable Read)
- 串行化(Serializable)
场景描述
用户在在线购物平台上购买了一款商品,该操作涉及以下步骤:
- 检查商品库存。
- 更新用户购物车。
- 创建订单。
- 更新库存。
- 扣款操作。
sql语句
代码语言:sql复制START TRANSACTION;
-- 检查库存
SELECT stock FROM products WHERE id = ?;
-- 如果库存大于0,继续执行以下语句
UPDATE shopping_cart SET quantity = quantity 1 WHERE user_id = ? AND product_id = ?;
INSERT INTO orders (user_id, product_id, quantity, total_price) VALUES (?, ?, ?, ?);
UPDATE products SET stock = stock - 1 WHERE id = ?;
UPDATE users SET balance = balance - ? WHERE id = ?;
COMMIT;
假设我们有一个在线购物平台的数据库,其中包含以下表:
products
:存储商品信息,包含id
,stock
等字段。shopping_cart
:存储用户的购物车信息,包含user_id
,product_id
,quantity
等字段。orders
:存储订单信息,包含user_id
,product_id
,quantity
,total_price
等字段。users
:存储用户信息,包含id
,balance
等字段。
Java代码
代码语言:java复制import java.sql.*;
public class ShoppingCartService {
private static final String URL = "jdbc:mysql://localhost:3306/shopping_platform";
private static final String USER = "root";
private static final String PASSWORD = "password";
public void purchaseProduct(int userId, int productId, int productQuantity, double total_price) {
Connection conn = null;
PreparedStatement checkStockStmt = null;
PreparedStatement updateCartStmt = null;
PreparedStatement createOrderStmt = null;
PreparedStatement updateStockStmt = null;
PreparedStatement updateUserBalanceStmt = null;
try {
conn = DriverManager.getConnection(URL, USER, PASSWORD);
conn.setAutoCommit(false); // 开始事务
// 检查库存
checkStockStmt = conn.prepareStatement("SELECT stock FROM products WHERE id = ?");
checkStockStmt.setInt(1, productId);
ResultSet rs = checkStockStmt.executeQuery();
if (!rs.next() || rs.getInt("stock") < 1) {
throw new Exception("Product out of stock.");
}
// 更新购物车
updateCartStmt = conn.prepareStatement("UPDATE shopping_cart SET quantity = quantity 1 WHERE user_id = ? AND product_id = ?");
updateCartStmt.setInt(1, userId);
updateCartStmt.setInt(2, productId);
updateCartStmt.executeUpdate();
// 创建订单
createOrderStmt = conn.prepareStatement("INSERT INTO orders (user_id, product_id, quantity, total_price) VALUES (?, ?, ?, ?)");
createOrderStmt.setInt(1, userId);
createOrderStmt.setInt(2, productId);
createOrderStmt.setInt(3, productQuantity);
createOrderStmt.setDouble(4, total_price);
createOrderStmt.executeUpdate();
// 更新库存
updateStockStmt = conn.prepareStatement("UPDATE products SET stock = stock - 1 WHERE id = ?");
updateStockStmt.setInt(1, productId);
updateStockStmt.executeUpdate();
// 扣款操作
updateUserBalanceStmt = conn.prepareStatement("UPDATE users SET balance = balance - ? WHERE id = ?");
updateUserBalanceStmt.setDouble(1, total_price);
updateUserBalanceStmt.setInt(2, userId);
updateUserBalanceStmt.executeUpdate();
conn.commit(); // 提交事务
} catch (Exception e) {
if (conn != null) {
try {
conn.rollback(); // 回滚事务
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 关闭资源
try {
if (checkStockStmt != null) checkStockStmt.close();
if (updateCartStmt != null) updateCartStmt.close();
if (createOrderStmt != null) createOrderStmt.close();
if (updateStockStmt != null) updateStockStmt.close();
if (updateUserBalanceStmt != null) updateUserBalanceStmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}