我是MySQL新手。请问您如何修改以下功能以确保在多个用户同时调用时不会引发锁定错误。
CREATE FUNCTION `get_val`(`P_TABLE` VARCHAR(50)) RETURNS int(11)
DETERMINISTIC
BEGIN
DECLARE pk_value INT DEFAULT 0;
DECLARE pk_found INT DEFAULT 0;
SELECT 1 INTO pk_found FROM pk_keys WHERE TABLE_NAME = P_TABLE;
IF pk_found = 1
THEN
UPDATE pk_keys SET TABLE_VALUE = (TABLE_VALUE + 1 ) WHERE TABLE_NAME = P_TABLE;
ELSE
INSERT INTO pk_keys VALUES ( P_TABLE, 1 );
END IF;
SELECT TABLE_VALUE INTO pk_value FROM pk_keys WHERE TABLE_NAME = P_TABLE;
RETURN pk_value;
END
感谢
答案 0 :(得分:1)
CREATE FUNCTION `get_val`(`P_TABLE` VARCHAR(50)) RETURNS int(11)
DETERMINISTIC
MODIFIES SQL DATA
BEGIN
DECLARE pk_value INT DEFAULT 0;
IF EXISTS (SELECT 1 FROM pk_keys WHERE TABLE_NAME = P_TABLE)
THEN
SELECT TABLE_VALUE + 1 INTO pk_value FROM pk_keys WHERE TABLE_NAME = P_TABLE FOR UPDATE;
UPDATE pk_keys SET TABLE_VALUE = pk_value WHERE TABLE_NAME = P_TABLE;
ELSE
SET pk_value = 1;
INSERT INTO pk_keys VALUES ( P_TABLE, pk_value );
END IF;
RETURN pk_value;
END
查看SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE Locking Reads
让我们看另一个例子:我们在a中有一个整数计数器字段 table child_codes,我们用它们为每个人分配一个唯一的标识符 孩子加入了桌子。使用其中任何一个都不是一个好主意 一致读取或共享模式读取以读取当前值 计数器,因为数据库的两个用户可能会看到相同的值 对于计数器,如果两个用户尝试,则会发生重复键错误 将具有相同标识符的子项添加到表中。
这里,LOCK IN SHARE MODE不是一个好的解决方案,因为如果有两个用户 同时读取计数器,其中至少有一个最终进入 尝试更新计数器时死锁。
要实现读取和递增计数器,首先执行a 使用FOR UPDATE锁定计数器的读取,然后递增 计数器。例如:
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
SELECT ... FOR UPDATE读取最新的可用数据,设置 它读取的每一行都有独占锁。因此,它设置相同的锁a 搜索到的SQL UPDATE将在行上设置。
我也替换了你的if条件。一旦找到行,EXISTS
就会停止。