Existe um banco de dados simples com duas tabelas: usuários e transações. A tabela de usuários é usada para armazenar informações do usuário e a tabela de transações é usada para armazenar informações de transações.
Primeiro, crie o banco de dados e as tabelas:
CREATE DATABASE IF NOT EXISTS my_database;
USE my_database;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
balance DECIMAL(10, 2) NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS transactions (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
type ENUM('deposit', 'withdraw') NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Insira alguns dados de teste:
INSERT INTO users (username, balance) VALUES
('lfsun-1', 1000.00),
('lfsun-2', 500.00),
('lfsun-4', 200.00);
Agora, usaremos uma transação para simular uma operação de transferência de dinheiro. Suponha que queremos transferir uma quantia de 100,00 de lfsun-1 para lfsun-2:
-- 开始事务
START TRANSACTION;
-- 更新 lfsun-1 的余额
UPDATE users
SET balance = balance - 100.00
WHERE username = 'lfsun-1';
-- 更新 lfsun-2 的余额
UPDATE users
SET balance = balance + 100.00
WHERE username = 'lfsun-2';
-- 向 transactions 表插入一条记录表示转账操作
INSERT INTO transactions (user_id, amount, type)
VALUES ((SELECT id FROM users WHERE username = 'lfsun-1'), 100.00, 'withdraw'),
((SELECT id FROM users WHERE username = 'lfsun-2'), 100.00, 'deposit');
-- 提交事务
COMMIT;
Agora, suponha que algo deu errado com a transferência e precisamos reverter a operação:
-- 开始事务
START TRANSACTION;
-- 更新 lfsun-1 的余额
UPDATE users
SET balance = balance - 100.00
WHERE username = 'lfsun-1';
-- 更新 lfsun-2 的余额
UPDATE users
SET balance = balance + 100.00
WHERE username = 'lfsun-2';
-- 向 transactions 表插入一条记录表示转账操作
INSERT INTO transactions (user_id, amount, type)
VALUES ((SELECT id FROM users WHERE username = 'lfsun-1'), 100.00, 'withdraw'),
((SELECT id FROM users WHERE username = 'lfsun-2'), 100.00, 'deposit');
-- 回滚事务
ROLLBACK;
Em alguns casos, pode ser necessário usar pontos de salvamento (SAVEPOINT) para obter um controle de transação mais refinado:
-- 开始事务
START TRANSACTION;
-- 更新 lfsun-1的余额
UPDATE users SET balance = balance - 100.00 WHERE username = 'lfsun-1';
-- 保存点1
SAVEPOINT point1;
-- 更新 lfsun-2 的余额
UPDATE users SET balance = balance + 100.00 WHERE username = 'lfsun-2';
-- 向 transactions 表插入一条记录表示转账操作
INSERT INTO transactions (user_id, amount, type) VALUES
((SELECT id FROM users WHERE username = 'lfsun-1'), 100.00, 'withdraw'),
((SELECT id FROM users WHERE username = 'lfsun-2'), 100.00, 'deposit');
-- 发生错误,回滚到保存点1
ROLLBACK TO point1;
-- 提交事务
COMMIT;
Por fim, demonstre o uso de bloqueios de tabela (LOCK TABLES e UNLOCK TABLES):
-- 锁定 users 表,防止其他会话对其进行修改
LOCK TABLES users WRITE;
-- 执行一些操作,例如更新或插入数据
-- 解锁 users 表
UNLOCK TABLES;