MYSQL触发器导致锁定

e4yzc0pl  于 2024-01-05  发布在  Mysql
关注(0)|答案(2)|浏览(171)

我有一个mysql表上的触发器,它插入到另一个表中(见下面的触发器)。
这个触发器似乎导致了另一个表的锁,从而阻止了同一个表中同时发生的其他插入操作。如果我删除这个触发器,其他插入操作就会按预期工作。
我需要找到一种方法来确保两个插入都发生。有没有其他方法可以帮助我编写触发器?
更多背景:这个触发器设置的表是Joomla网站扩展的一部分,它是一个表单,可以将字段插入到这个扩展的表中-触发器获取一些新的.fields并将它们插入到Joomla核心表中用于自定义字段(ch54b_fields_values)。扩展本身也会写入Joomla表中用于自定义字段,作为初始插入的一部分。
任何帮助都是感激的。我不是这方面的Maven,所以不想玩的东西,并导致其他问题。

  1. IF (new.catid = '131')
  2. THEN
  3. INSERT INTO ch54b_fields_values (field_id, item_id, value) VALUES ('2', new.id, new.created_by);
  4. END IF

字符串
我尝试在插入之前和之后执行触发器,结果是相同的。

d5vmydt9

d5vmydt91#

你得问问自己:
1.我怎么知道问题是由锁引起的?
您的答案可能是所有失败的插入都发生在插入运行时。但是:
1.我的错误是在触发器运行时由于表锁而发生的,还是在同一时间发生的?
现在这是你需要问自己的一个关键问题。所以,检查你的MySQL日志,看看为什么插入失败,插入是什么。如果错误消息澄清了你的确切问题,那么你可以解决它。如果没有,那么继续阅读。创建一个数据库的副本,并导入到你可以自由实验的地方。你对自己的下一个问题:
1.在没有触发触发器的情况下,我的插入是否在我的副本上成功?(您甚至可以从您的副本中删除此触发器)
如果插入成功,那么很可能是表锁问题。
如果这是一个表锁问题,如果你还没有这样做,考虑切换到InnoDB。此外,你可能会失败的插入可以放入一个事务中,并在失败时重试。如果这个触发器引起太多头痛,您可以考虑将其删除,并在应用程序代码中重新组织插入和更新,而不是触发器。您可以创建一个队列,其中包含要在你有冲突的地方
如果插入操作在稍后仍然没有成功,那么它不是由于锁而失败,而是由于数据完整性约束等原因。您可能希望重新插入具有相同唯一值(例如相同id或相同唯一外键)的相同记录,或者您可能打算插入具有引用不再存在的记录的外键的记录。
因此,阅读日志,调试和实验。每个实验都会让您更接近解决方案,而与实验结果无关。

wsewodh2

wsewodh22#

您似乎遇到了由触发器引起的表锁问题。这是使用触发器修改另一个表时的常见问题,因为它可能导致并发访问问题。以下是一些可能有所帮助的建议:

*使用SELECT ... FOR UPDATE模式:此模式用于读取最新的可用数据,并在读取的每一行上设置排他锁1。这有助于防止两个触发器同时运行并更新同一条记录。
*更换存储引擎:如果表的存储引擎为MyISAM,则可能导致锁。MyISAM使用表级锁,可以在操作过程中锁定整个表。将存储引擎更换为InnoDB,使用行级锁,可能会解决问题2。

  • 使用分段表:另一种解决方案是使用一个“staging”表来保存挂起的更改。然后您可以在MySQL中创建一个事件来读取此staging表并执行所需的更改3。这可以帮助避免触发器导致的循环引用。
    *重写触发器:您可以考虑重写触发器,以便更好地处理并发。例如,您可以使用BEFORE触发器来设置要插入到ch54b_fields_values45中的值。

下面是一个如何使用BEFORE方法重写触发器的示例:

  1. CREATE TRIGGER before_insert_on_table
  2. BEFORE INSERT ON your_table
  3. FOR EACH ROW
  4. BEGIN
  5. IF NEW.catid = '131' THEN
  6. SET @field_id = '2', @item_id = NEW.id, @value = NEW.created_by;
  7. END IF;
  8. END;

字符串
然后,您可以在表上的插入操作完成后将值插入到ch54b_fields_values中。
请注意,这些只是建议,您应该彻底测试它们,以确保它们在您的特定用例中按预期工作。

展开查看全部

相关问题