mysql插入时防止账号重复插入迸发
方案零 数据库添加唯一索引
ALTER TABLE your_table ADD UNIQUE (name);
当数据库表有软删除 IsDeleted 字段的时候 就只能用以下方式了
注: 网友提了一种方案就是 IsDeleted 设置null 唯一索引不删除 为null的标识删除(此方案待验证)
注: 网友提了一种方案就是 IsDeleted 设置null 唯一索引不删除 为null的标识删除(此方案待验证)
方案一 INSERT INTO SELECT
CREATE TABLE Table_Test (
Id INT ( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT,
`Name` VARCHAR ( 10 ) DEFAULT NULL,
Mobile VARCHAR ( 20 ) DEFAULT NULL,
PRIMARY KEY ( Id ),
UNIQUE INDEX Idx_Name ( `Name` ) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 0 DEFAULT CHARSET = UTF8;
INSERT INTO Table_Test (`Name`,Mobile) SELECT '王4','13578901236' FROM DUAL WHERE NOT EXISTS (SELECT NAME FROM Table_Test WHERE NAME = '王4')
方案二 触发器
CREATE TABLE `table_test` (
`Id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`Name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_ci NULL DEFAULT NULL,
`Mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_ci NULL DEFAULT NULL,
`IsDeleted` bit(1) NOT NULL,
PRIMARY KEY (`Id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_as_ci ROW_FORMAT = Dynamic;
-- 插入触发器
DELIMITER $$
CREATE TRIGGER trg_CheckUniqueNameOnInsert
BEFORE INSERT ON Table_Test
FOR EACH ROW
BEGIN
IF NEW.IsDeleted = 0 THEN
IF EXISTS (
SELECT 1
FROM Table_Test
WHERE Name = NEW.Name AND IsDeleted = 0
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Duplicate entry for Name with IsDeleted=0';
END IF;
END IF;
END$$
-- 更新触发器
DELIMITER $$
CREATE TRIGGER trg_CheckUniqueNameOnUpdate
BEFORE UPDATE ON Table_Test
FOR EACH ROW
BEGIN
-- 检查更新后的记录是否满足唯一性约束
IF NEW.IsDeleted = 0 THEN
IF EXISTS (
SELECT 1
FROM Table_Test
WHERE Name = NEW.Name AND IsDeleted = 0 AND Id <> NEW.Id
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Duplicate entry for Name with IsDeleted=0 on update';
END IF;
END IF;
END$$
DELIMITER ;
方案三 分布式事务锁
using StackExchange.Redis;
using System;
class Program
{
static void Main(string[] args)
{
// 连接到 Redis
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
IDatabase db = redis.GetDatabase();
string key = "mykey";
// 监控键
var transaction = db.CreateTransaction();
transaction.AddCondition(Condition.KeyEquals(key, "oldvalue"));
// 设置新值
transaction.StringSetAsync(key, "newvalue");
// 提交事务
bool committed = transaction.Execute();
if (committed)
{
Console.WriteLine("事务成功执行!");
}
else
{
Console.WriteLine("事务失败:键已被其他客户端修改!");
}
redis.Close();
}
}
方案四 悲观锁
SELECT * FROM Table_Test WHERE NAME='xxx' AND IsDeleted = 0 FOR UPDATE
方案五 事务级别最高
using (var context = new YourDbContext())
{
using (var transaction = context.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
try
{
// 检查是否存在未删除的记录
var exists = context.TableTest
.Any(t => t.Name == "王4" && t.IsDeleted == 0);
if (!exists)
{
// 插入新记录
var newRecord = new TableTest
{
Name = "王4",
Mobile = "13578901236",
IsDeleted = 0 // 标记为未删除
};
context.TableTest.Add(newRecord);
context.SaveChanges();
}
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
}

浙公网安备 33010602011771号