495 lines
16 KiB
SQL
495 lines
16 KiB
SQL
-- ============================================
|
|
-- 压力测试数据生成脚本
|
|
-- 用于生成大量测试数据以进行性能测试
|
|
-- ============================================
|
|
|
|
SET NAMES utf8mb4;
|
|
SET FOREIGN_KEY_CHECKS = 0;
|
|
|
|
-- 清理测试数据(可选,谨慎使用)
|
|
-- DELETE FROM wallet_ledger WHERE user_id > 1000;
|
|
-- DELETE FROM rental_orders WHERE id > 100;
|
|
-- DELETE FROM rental_listings WHERE id > 100;
|
|
-- DELETE FROM game_accounts WHERE id > 100;
|
|
-- DELETE FROM users WHERE id > 1000;
|
|
|
|
-- ============================================
|
|
-- 1. 批量生成用户数据(10000个用户)
|
|
-- ============================================
|
|
DROP PROCEDURE IF EXISTS generate_users;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE generate_users(IN batch_size INT)
|
|
BEGIN
|
|
DECLARE i INT DEFAULT 1;
|
|
DECLARE phone_num VARCHAR(32);
|
|
DECLARE nick VARCHAR(64);
|
|
|
|
WHILE i <= batch_size DO
|
|
SET phone_num = CONCAT('138', LPAD(i, 8, '0'));
|
|
SET nick = CONCAT('测试用户', i);
|
|
|
|
INSERT INTO users (
|
|
phone, nickname, realname_status, risk_status,
|
|
credit_score, status, created_at
|
|
) VALUES (
|
|
phone_num, nick,
|
|
CASE WHEN i % 10 = 0 THEN 'unverified' ELSE 'verified' END,
|
|
CASE WHEN i % 100 = 0 THEN 'frozen' ELSE 'normal' END,
|
|
80 + (i % 20),
|
|
'active',
|
|
DATE_SUB(NOW(), INTERVAL (i % 365) DAY)
|
|
) ON DUPLICATE KEY UPDATE id=id;
|
|
|
|
-- 为已实名用户创建实名记录
|
|
IF i % 10 != 0 THEN
|
|
INSERT INTO user_realname (
|
|
user_id, provider, status, masked_name, masked_id_no, verified_at
|
|
) VALUES (
|
|
LAST_INSERT_ID(), 'mock', 'success',
|
|
CONCAT('张*', CHAR(65 + (i % 26))),
|
|
CONCAT('3301**********', LPAD(i % 10000, 4, '0')),
|
|
DATE_SUB(NOW(), INTERVAL (i % 300) DAY)
|
|
) ON DUPLICATE KEY UPDATE user_id=user_id;
|
|
END IF;
|
|
|
|
-- 为用户创建钱包
|
|
INSERT INTO wallet_accounts (user_id, available_balance, frozen_balance, status)
|
|
VALUES (
|
|
LAST_INSERT_ID(),
|
|
(i % 10) * 100.00,
|
|
(i % 5) * 50.00,
|
|
'active'
|
|
) ON DUPLICATE KEY UPDATE user_id=user_id;
|
|
|
|
SET i = i + 1;
|
|
|
|
-- 每1000条提交一次
|
|
IF i % 1000 = 0 THEN
|
|
COMMIT;
|
|
END IF;
|
|
END WHILE;
|
|
|
|
COMMIT;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ============================================
|
|
-- 2. 批量生成游戏账号和商品(50000个商品)
|
|
-- ============================================
|
|
DROP PROCEDURE IF EXISTS generate_listings;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE generate_listings(IN batch_size INT)
|
|
BEGIN
|
|
DECLARE i INT DEFAULT 1;
|
|
DECLARE user_id_val BIGINT;
|
|
DECLARE account_id_val BIGINT;
|
|
DECLARE price_val DECIMAL(12,2);
|
|
DECLARE deposit_val DECIMAL(12,2);
|
|
DECLARE verified_user_min BIGINT;
|
|
DECLARE verified_user_max BIGINT;
|
|
DECLARE user_pick BIGINT;
|
|
|
|
SELECT MIN(id), MAX(id)
|
|
INTO verified_user_min, verified_user_max
|
|
FROM users
|
|
WHERE realname_status = 'verified';
|
|
|
|
IF verified_user_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已实名用户';
|
|
END IF;
|
|
|
|
WHILE i <= batch_size DO
|
|
-- 近似随机选择一个用户作为号主,避免 ORDER BY RAND() 全表排序。
|
|
SET user_id_val = NULL;
|
|
SET user_pick = verified_user_min + FLOOR(RAND() * (verified_user_max - verified_user_min + 1));
|
|
SELECT id INTO user_id_val FROM users
|
|
WHERE id >= user_pick AND realname_status = 'verified'
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF user_id_val IS NULL THEN
|
|
SELECT id INTO user_id_val FROM users
|
|
WHERE realname_status = 'verified'
|
|
ORDER BY id LIMIT 1;
|
|
END IF;
|
|
|
|
-- 创建游戏账号
|
|
INSERT INTO game_accounts (
|
|
owner_id, game_name, server_region, login_platform,
|
|
title, description, rank_level, haf_coin_amount, status
|
|
) VALUES (
|
|
user_id_val,
|
|
'delta_force',
|
|
CASE (i % 4)
|
|
WHEN 0 THEN '亚服'
|
|
WHEN 1 THEN '美服'
|
|
WHEN 2 THEN '欧服'
|
|
ELSE '国服'
|
|
END,
|
|
CASE (i % 3)
|
|
WHEN 0 THEN 'Steam'
|
|
WHEN 1 THEN 'Epic'
|
|
ELSE 'WeGame'
|
|
END,
|
|
CONCAT('账号', i, ' 高分段'),
|
|
CONCAT('这是一个测试账号,编号', i),
|
|
CASE (i % 5)
|
|
WHEN 0 THEN '青铜'
|
|
WHEN 1 THEN '白银'
|
|
WHEN 2 THEN '黄金'
|
|
WHEN 3 THEN '铂金'
|
|
ELSE '钻石'
|
|
END,
|
|
(i % 100) * 10000,
|
|
'published'
|
|
);
|
|
|
|
SET account_id_val = LAST_INSERT_ID();
|
|
|
|
-- 创建租号商品
|
|
SET price_val = 5.00 + (i % 20) * 0.5;
|
|
SET deposit_val = 100.00 + (i % 10) * 50.00;
|
|
|
|
INSERT INTO rental_listings (
|
|
listing_no, account_id, owner_id, price, deposit_amount,
|
|
in_transaction, status, review_status, published_at
|
|
) VALUES (
|
|
CONCAT(
|
|
DATE_FORMAT(DATE_SUB(NOW(), INTERVAL (i % 90) DAY), '%Y%m%d'),
|
|
LPAD(FLOOR((i - 1) / 90) + 1, 4, '0')
|
|
),
|
|
account_id_val,
|
|
user_id_val,
|
|
price_val,
|
|
deposit_val,
|
|
CASE WHEN i % 10 = 0 THEN 1 ELSE 0 END,
|
|
CASE
|
|
WHEN i % 20 = 0 THEN 'offline'
|
|
WHEN i % 15 = 0 THEN 'draft'
|
|
ELSE 'published'
|
|
END,
|
|
CASE
|
|
WHEN i % 15 = 0 THEN 'pending'
|
|
WHEN i % 30 = 0 THEN 'rejected'
|
|
ELSE 'approved'
|
|
END,
|
|
DATE_SUB(NOW(), INTERVAL (i % 90) DAY)
|
|
);
|
|
|
|
SET i = i + 1;
|
|
|
|
IF i % 1000 = 0 THEN
|
|
COMMIT;
|
|
END IF;
|
|
END WHILE;
|
|
|
|
INSERT INTO listing_no_sequences (biz_date, next_seq)
|
|
SELECT LEFT(listing_no, 8), MAX(CAST(SUBSTRING(listing_no, 9) AS UNSIGNED))
|
|
FROM rental_listings
|
|
GROUP BY LEFT(listing_no, 8)
|
|
ON DUPLICATE KEY UPDATE next_seq = GREATEST(next_seq, VALUES(next_seq));
|
|
|
|
COMMIT;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ============================================
|
|
-- 3. 批量生成订单数据(30000个订单)
|
|
-- ============================================
|
|
DROP PROCEDURE IF EXISTS generate_orders;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE generate_orders(IN batch_size INT)
|
|
BEGIN
|
|
DECLARE i INT DEFAULT 1;
|
|
DECLARE listing_id_val BIGINT;
|
|
DECLARE account_id_val BIGINT;
|
|
DECLARE owner_id_val BIGINT;
|
|
DECLARE renter_id_val BIGINT;
|
|
DECLARE order_no_val VARCHAR(64);
|
|
DECLARE rent_amount_val DECIMAL(12,2);
|
|
DECLARE deposit_val DECIMAL(12,2);
|
|
DECLARE listing_min BIGINT;
|
|
DECLARE listing_max BIGINT;
|
|
DECLARE listing_pick BIGINT;
|
|
DECLARE verified_user_min BIGINT;
|
|
DECLARE verified_user_max BIGINT;
|
|
DECLARE user_pick BIGINT;
|
|
|
|
SELECT MIN(id), MAX(id)
|
|
INTO listing_min, listing_max
|
|
FROM rental_listings
|
|
WHERE status IN ('published', 'active') AND review_status = 'approved';
|
|
|
|
SELECT MIN(id), MAX(id)
|
|
INTO verified_user_min, verified_user_max
|
|
FROM users
|
|
WHERE realname_status = 'verified';
|
|
|
|
IF listing_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已上架商品';
|
|
END IF;
|
|
IF verified_user_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已实名用户';
|
|
END IF;
|
|
|
|
WHILE i <= batch_size DO
|
|
-- 近似随机选择一个上架商品,避免 ORDER BY RAND() 全表排序。
|
|
SET listing_id_val = NULL;
|
|
SET listing_pick = listing_min + FLOOR(RAND() * (listing_max - listing_min + 1));
|
|
SELECT rl.id, rl.account_id, rl.owner_id, rl.price, rl.deposit_amount
|
|
INTO listing_id_val, account_id_val, owner_id_val, rent_amount_val, deposit_val
|
|
FROM rental_listings rl
|
|
WHERE rl.id >= listing_pick
|
|
AND rl.status IN ('published', 'active')
|
|
AND rl.review_status = 'approved'
|
|
ORDER BY rl.id LIMIT 1;
|
|
|
|
IF listing_id_val IS NULL THEN
|
|
SELECT rl.id, rl.account_id, rl.owner_id, rl.price, rl.deposit_amount
|
|
INTO listing_id_val, account_id_val, owner_id_val, rent_amount_val, deposit_val
|
|
FROM rental_listings rl
|
|
WHERE rl.status IN ('published', 'active')
|
|
AND rl.review_status = 'approved'
|
|
ORDER BY rl.id LIMIT 1;
|
|
END IF;
|
|
|
|
-- 近似随机选择一个租客(不能是号主本人)。
|
|
SET renter_id_val = NULL;
|
|
SET user_pick = verified_user_min + FLOOR(RAND() * (verified_user_max - verified_user_min + 1));
|
|
SELECT id INTO renter_id_val FROM users
|
|
WHERE id >= user_pick AND id != owner_id_val AND realname_status = 'verified'
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF renter_id_val IS NULL THEN
|
|
SELECT id INTO renter_id_val FROM users
|
|
WHERE id != owner_id_val AND realname_status = 'verified'
|
|
ORDER BY id LIMIT 1;
|
|
END IF;
|
|
|
|
IF renter_id_val IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的租客用户';
|
|
END IF;
|
|
|
|
SET order_no_val = CONCAT('ORD', DATE_FORMAT(NOW(), '%Y%m%d'), LPAD(i, 8, '0'));
|
|
SET rent_amount_val = rent_amount_val * 24; -- 24小时租金
|
|
|
|
INSERT INTO rental_orders (
|
|
order_no, listing_id, account_id, owner_id, renter_id,
|
|
estimated_duration_hours, rent_amount, owner_rent_amount,
|
|
deposit_amount, platform_fee, status, handoff_status,
|
|
settlement_status, rented_at, created_at
|
|
) VALUES (
|
|
order_no_val,
|
|
listing_id_val,
|
|
account_id_val,
|
|
owner_id_val,
|
|
renter_id_val,
|
|
24,
|
|
rent_amount_val,
|
|
rent_amount_val * 0.95, -- 号主实得95%
|
|
deposit_val,
|
|
rent_amount_val * 0.05, -- 平台5%手续费
|
|
CASE (i % 10)
|
|
WHEN 0 THEN 'pending_payment'
|
|
WHEN 1 THEN 'cancelled'
|
|
WHEN 2 THEN 'closed'
|
|
ELSE 'completed'
|
|
END,
|
|
CASE (i % 10)
|
|
WHEN 0 THEN 'none'
|
|
WHEN 1 THEN 'none'
|
|
WHEN 2 THEN 'owner_delivered'
|
|
ELSE 'owner_received'
|
|
END,
|
|
CASE (i % 10)
|
|
WHEN 0 THEN 'unsettled'
|
|
WHEN 1 THEN 'unsettled'
|
|
ELSE 'settled'
|
|
END,
|
|
DATE_SUB(NOW(), INTERVAL (i % 60) DAY),
|
|
DATE_SUB(NOW(), INTERVAL (i % 60) DAY)
|
|
);
|
|
|
|
SET i = i + 1;
|
|
|
|
IF i % 1000 = 0 THEN
|
|
COMMIT;
|
|
END IF;
|
|
END WHILE;
|
|
|
|
COMMIT;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ============================================
|
|
-- 4. 批量生成钱包流水(100000条流水)
|
|
-- ============================================
|
|
DROP PROCEDURE IF EXISTS generate_wallet_ledger;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE generate_wallet_ledger(IN batch_size INT)
|
|
BEGIN
|
|
DECLARE i INT DEFAULT 1;
|
|
DECLARE user_id_val BIGINT;
|
|
DECLARE order_id_val BIGINT;
|
|
DECLARE ledger_no_val VARCHAR(64);
|
|
DECLARE amount_val DECIMAL(12,2);
|
|
DECLARE user_min BIGINT;
|
|
DECLARE user_max BIGINT;
|
|
DECLARE order_min BIGINT;
|
|
DECLARE order_max BIGINT;
|
|
DECLARE user_pick BIGINT;
|
|
DECLARE order_pick BIGINT;
|
|
|
|
SELECT MIN(id), MAX(id) INTO user_min, user_max FROM users;
|
|
SELECT MIN(id), MAX(id) INTO order_min, order_max FROM rental_orders;
|
|
|
|
IF user_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的用户';
|
|
END IF;
|
|
|
|
WHILE i <= batch_size DO
|
|
-- 近似随机选择用户,避免 ORDER BY RAND() 全表排序。
|
|
SET user_id_val = NULL;
|
|
SET user_pick = user_min + FLOOR(RAND() * (user_max - user_min + 1));
|
|
SELECT id INTO user_id_val FROM users
|
|
WHERE id >= user_pick
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF user_id_val IS NULL THEN
|
|
SELECT id INTO user_id_val FROM users ORDER BY id LIMIT 1;
|
|
END IF;
|
|
|
|
-- 随机关联订单(50%概率)
|
|
IF RAND() > 0.5 AND order_min IS NOT NULL THEN
|
|
SET order_id_val = NULL;
|
|
SET order_pick = order_min + FLOOR(RAND() * (order_max - order_min + 1));
|
|
SELECT id INTO order_id_val FROM rental_orders
|
|
WHERE id >= order_pick
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF order_id_val IS NULL THEN
|
|
SELECT id INTO order_id_val FROM rental_orders ORDER BY id LIMIT 1;
|
|
END IF;
|
|
ELSE
|
|
SET order_id_val = NULL;
|
|
END IF;
|
|
|
|
SET ledger_no_val = CONCAT('LDG', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s'), LPAD(i, 6, '0'));
|
|
SET amount_val = (i % 500) + RAND() * 100;
|
|
|
|
INSERT INTO wallet_ledger (
|
|
ledger_no, user_id, order_id, direction, amount,
|
|
balance_after, balance_type, biz_type, biz_no, remark, created_at
|
|
) VALUES (
|
|
ledger_no_val,
|
|
user_id_val,
|
|
order_id_val,
|
|
CASE WHEN i % 2 = 0 THEN 'in' ELSE 'out' END,
|
|
amount_val,
|
|
1000.00 + (i % 1000),
|
|
CASE WHEN i % 5 = 0 THEN 'frozen' ELSE 'available' END,
|
|
CASE (i % 6)
|
|
WHEN 0 THEN 'rent_payment'
|
|
WHEN 1 THEN 'deposit_freeze'
|
|
WHEN 2 THEN 'settlement'
|
|
WHEN 3 THEN 'refund'
|
|
WHEN 4 THEN 'recharge'
|
|
ELSE 'withdraw'
|
|
END,
|
|
CONCAT('BIZ', LPAD(i, 10, '0')),
|
|
CONCAT('测试流水', i),
|
|
DATE_SUB(NOW(), INTERVAL (i % 180) DAY)
|
|
);
|
|
|
|
SET i = i + 1;
|
|
|
|
IF i % 1000 = 0 THEN
|
|
COMMIT;
|
|
END IF;
|
|
END WHILE;
|
|
|
|
COMMIT;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ============================================
|
|
-- 5. 批量生成聊天消息(50000条消息)
|
|
-- ============================================
|
|
DROP PROCEDURE IF EXISTS generate_chat_messages;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE generate_chat_messages(IN batch_size INT)
|
|
BEGIN
|
|
DECLARE i INT DEFAULT 1;
|
|
DECLARE conv_id BIGINT;
|
|
DECLARE user_id_val BIGINT;
|
|
DECLARE conv_min BIGINT;
|
|
DECLARE conv_max BIGINT;
|
|
DECLARE user_min BIGINT;
|
|
DECLARE user_max BIGINT;
|
|
DECLARE conv_pick BIGINT;
|
|
DECLARE user_pick BIGINT;
|
|
|
|
SELECT MIN(id), MAX(id) INTO conv_min, conv_max FROM chat_conversations;
|
|
SELECT MIN(id), MAX(id) INTO user_min, user_max FROM users;
|
|
|
|
IF conv_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的聊天会话';
|
|
END IF;
|
|
IF user_min IS NULL THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的用户';
|
|
END IF;
|
|
|
|
WHILE i <= batch_size DO
|
|
-- 近似随机选择一个会话和发送者,避免 ORDER BY RAND() 全表排序。
|
|
SET conv_id = NULL;
|
|
SET conv_pick = conv_min + FLOOR(RAND() * (conv_max - conv_min + 1));
|
|
SELECT id INTO conv_id FROM chat_conversations
|
|
WHERE id >= conv_pick
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF conv_id IS NULL THEN
|
|
SELECT id INTO conv_id FROM chat_conversations ORDER BY id LIMIT 1;
|
|
END IF;
|
|
|
|
IF conv_id IS NOT NULL THEN
|
|
SET user_id_val = NULL;
|
|
SET user_pick = user_min + FLOOR(RAND() * (user_max - user_min + 1));
|
|
SELECT id INTO user_id_val FROM users
|
|
WHERE id >= user_pick
|
|
ORDER BY id LIMIT 1;
|
|
|
|
IF user_id_val IS NULL THEN
|
|
SELECT id INTO user_id_val FROM users ORDER BY id LIMIT 1;
|
|
END IF;
|
|
|
|
INSERT INTO chat_messages (
|
|
conversation_id, sender_type, sender_id, sender_role,
|
|
content_type, content, created_at
|
|
) VALUES (
|
|
conv_id,
|
|
'user',
|
|
user_id_val,
|
|
CASE WHEN i % 2 = 0 THEN 'owner' ELSE 'renter' END,
|
|
'text',
|
|
CONCAT('这是测试消息', i, ',内容随机生成用于压力测试'),
|
|
DATE_SUB(NOW(), INTERVAL (i % 30) DAY)
|
|
);
|
|
END IF;
|
|
|
|
SET i = i + 1;
|
|
|
|
IF i % 1000 = 0 THEN
|
|
COMMIT;
|
|
END IF;
|
|
END WHILE;
|
|
|
|
COMMIT;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ============================================
|
|
-- 本文件只创建存储过程,不直接生成数据。
|
|
-- 请使用 scripts/stress_test.sh data 按参数生成,避免意外重复造数。
|
|
-- ============================================
|
|
|
|
SET FOREIGN_KEY_CHECKS = 1;
|