【问题标题】:Lock multiple tables with aliases doesn't work使用别名锁定多个表不起作用
【发布时间】:2019-11-01 23:08:42
【问题描述】:

我试图通过创建 3 个临时表(不是 CREATE TEMPORARY TABLE..)然后将数据传输到原始表来编写一些查询以在我的数据库的 3 个表中插入一些值。在这样做时,我想锁定表,因为其中一个表将包含其他值以及其他表的最后一个索引值。 我已经尝试锁定表及其别名,但仍然出现错误:

表 'table_one_1' 没有被 LOCK TABLES 锁定。下面是一个 为简单起见,修改了代码示例。

我做错了什么?

UPDATED:
    DROP TABLE IF EXISTS anx_name_tmp;CREATE TABLE anx_name_tmp LIKE anx_name;
    DROP TABLE IF EXISTS proc_name_tmp;CREATE TABLE proc_name_tmp LIKE proc_name;
    DROP TABLE IF EXISTS proc_anx_tmp;CREATE TABLE proc_anx_tmp LIKE proc_anx;
    LOCK TABLES proc_anx WRITE, proc_anx as proc_anx_1 READ ,proc_name WRITE,proc_name as proc_name_1 READ, anx_name WRITE,anx_name as anx_name_1 READ, proc_anx_tmp WRITE, proc_anx_tmp as proc_anx_tmp_1 READ ,proc_name_tmp WRITE,proc_name_tmp as proc_name_tmp_1 READ, anx_name_tmp WRITE,anx_name_tmp as anx_name_tmp_1 READ ;
    INSERT INTO anx_name_tmp(anx_name,version,anx_full_name,code) VALUES ('demo_1cOAHfl.docx','nc,a','','');
    INSERT INTO proc_name_tmp(proc_den,version,proc_full_name,code) VALUES ('demo_px5MiBh.pdf','nc,a','xbsj','False');
    INSERT INTO proc_anx_tmp(proc_id,anx_id,date_proc_anx,proc_id_orig,proc_anx_united,proc_category_id,user_log_id,change_req_id) VALUES ((SELECT proc_id +1 FROM proc_name as proc_name_1 ORDER BY proc_id DESC LIMIT 1),(SELECT anx_id +1 FROM anx_name as anx_name_1 ORDER BY anx_id DESC LIMIT 1),'2019-06-19',(SELECT proc_id +1 FROM proc_name as proc_name_1 ORDER BY proc_id DESC LIMIT 1),(SELECT proc_anx_id +1 FROM proc_anx as proc_anx_1 ORDER BY proc_anx_id DESC LIMIT 1),'3','5','0');

    ALTER TABLE anx_name_tmp CHANGE COLUMN anx_id anx_id INT(11) NULL, DROP PRIMARY KEY ;UPDATE anx_name_tmp SET anx_id = 0 ;
    INSERT INTO anx_name SELECT * FROM anx_name_tmp as anx_name_tmp_1;
    ALTER TABLE proc_name_tmp CHANGE COLUMN proc_id proc_id INT(11) NULL, DROP PRIMARY KEY ;UPDATE proc_name_tmp SET proc_id = 0 ;
    INSERT INTO proc_name SELECT * FROM proc_name_tmp as proc_name_tmp_1;ALTER TABLE proc_anx_tmp CHANGE COLUMN proc_anx_id proc_anx_id INT(11) NULL, DROP PRIMARY KEY ;UPDATE proc_anx_tmp SET proc_anx_id = 0 ;
    INSERT INTO proc_anx SELECT * FROM proc_anx_tmp as proc_anx_tmp_1;
    UNLOCK TABLES

这是实际的代码。 我正在使用 InnoDB 存储。 我正在阅读我可以使用innodb_autoinc_lock_mode,但我不确定它如何以及是否可以实现我正在寻找的内容:锁定我从中获取主键的表并将其存储到第三个表中。

【问题讨论】:

  • “为简单起见,下面是经过修改的代码示例” 请参阅Why should I provide a Minimal Reproducible Example for a very simple SQL query?,您还应该提供示例数据和预期结果..
  • 它是准确的代码,除了表和字段的名称。也不包括这些值。如果我排除 LOCK 和 UNLOCK 部分,代码工作得很好。
  • 您的示例代码不起作用。虽然您可以使用伪代码,但它会阻止包括您在内的任何人相对简单地测试它的正确性。至少锁应该代表你在做什么。您多次锁定同一个表/表别名,这是不允许的(例如table_one read,table_one Write)。由于您的问题很可能是您的实际锁定语句中的错误,因此将其替换为甚至不起作用的东西也无济于事。 (我怀疑您用相同的名称替换了 2 个原始表)
  • 请参阅How to ask,如果没有此问题,您“需要”给出一个可重现的示例(包括示例数据和预期结果)是不清楚的,很可能不会回答,很可能会被投票关闭正因为如此。

标签: mysql


【解决方案1】:

虽然您使用别名的意图是正确的,但您仍然必须坚持the rule

您不能在单个查询中使用相同的名称多次引用锁定的表。改为使用别名,并为表和每个别名获取单独的锁

这包括两次使用别名,您正在这样做

INSERT INTO proc_anx_tmp (...) VALUES ( 
  (SELECT proc_id +1 FROM proc_name as proc_name_1 ORDER BY proc_id DESC LIMIT 1),
  ...
  (SELECT proc_id +1 FROM proc_name as proc_name_1 ORDER BY proc_id DESC LIMIT 1)
  ... );

替换其中一个别名。由于您实际上并没有在此查询中使用没有别名的proc_name,并且您(写入)锁定了未别名的表,因此您只需删除其中一个别名。

【讨论】:

  • 顺便说一句:我不完全确定你在用那个查询做什么。看起来您希望将自动增量值设置为无间隙顺序。这不是您应该需要/不想做的事情,自动增量 ID 并非旨在无缝,只是独一无二,您不应该期望它们如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-21
相关资源
最近更新 更多