Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql &引用;锁的总数超过了锁表的大小;删除267条记录_Mysql_Locking_Innodb_Sql Delete - Fatal编程技术网

Mysql &引用;锁的总数超过了锁表的大小;删除267条记录

Mysql &引用;锁的总数超过了锁表的大小;删除267条记录,mysql,locking,innodb,sql-delete,Mysql,Locking,Innodb,Sql Delete,我正试图从大约4000万张唱片中删除267张。查询如下所示: delete from pricedata where pricedate > '20120413' pricedate是一个char(8)字段 我知道如何调整innodb\u buffer\u pool\u size,但如果可以的话 select from pricedata where pricedate > '20120413' 并获得267条记录(仅此而已),没有错误,为什么它会在删除时阻塞 如果调整innod

我正试图从大约4000万张唱片中删除267张。查询如下所示:

delete from pricedata
where
pricedate > '20120413'
pricedate是一个
char(8)
字段

我知道如何调整innodb\u buffer\u pool\u size,但如果可以的话

select from pricedata
where
pricedate > '20120413'
并获得267条记录(仅此而已),没有错误,为什么它会在删除时阻塞


如果调整
innodb\u buffer\u pool\u size
不起作用,我该怎么办?

您似乎没有关于
pricedate
的索引(或者
MySQL
出于某种原因没有使用此索引)

使用
REPEATABLE READ
(默认事务隔离级别),
InnoDB
将共享锁放在查询读取和筛选出的记录上,您似乎没有足够的空间容纳
40M

要解决此问题,请使用以下任一解决方案:

  • pricedate
    上创建索引(如果不存在)(可能需要时间)

  • 将查询分成更小的块:

    DELETE
    FROM    pricedata
    WHERE   pricedate > '20120413'
            AND id BETWEEN 1 AND 1000000
    
    DELETE
    FROM    pricedata
    WHERE   pricedate > '20120413'
            AND id BETWEEN 1000001 AND 2000000
    
    等等(根据需要更改
    id
    范围)。请注意,每条语句都应该在自己的事务中运行(如果
    AUTOCOMMIT
    处于关闭状态,请不要忘记在每条语句之后提交)

  • 使用
    readcommitted
    事务隔离级别运行
    DELETE
    查询。一旦记录被读取,它将使InnoDB解除锁定。如果在语句模式下使用二进制日志,并且不允许binlog不安全查询(这是默认设置),则此操作将不起作用


  • 工作原理:将innodb缓冲池大小更改为256M(请参见Quassnoi原始评论下的评论)。

    (虽然回答较晚,但当人们在谷歌上发现这个问题时,拥有它总是很好的)

    不必改变innodb_buffer_pool_大小或创建索引的解决方案可以是限制要删除的行数

    因此,在您的案例中,
    从pricedata中删除,其中pricedata>“20120413”限制为100例如。
    这将删除100行,留下167行。因此,您可以再次运行相同的查询并删除另外100个查询。
    在过去的67年里,这很棘手。。。当数据库中剩余的行数小于给定的限制时,您将再次遇到关于锁数的错误。可能是因为服务器将搜索更多匹配的行以填充100行。
    在这种情况下,使用
    limit 67
    删除最后一部分。 (当然,您也可以在一开始就使用
    limit267

    对于那些喜欢写剧本的人。。。我在bash脚本中使用了一个很好的示例来清理旧数据:

       # Count the number of rows left to be deleted
       QUERY="select count(*) from pricedata where pricedata > '20120413';"
       AMOUNT=`${MYSQL} -u ${MYSQL_USER} -p${MYSQL_PWD} -e "${QUERY}" ${DB} | tail -1`
       ERROR=0
       while [ ${AMOUNT} -gt 0 -a ${ERROR} -eq 0 ]
       do
          ${LOGGER} "   ${AMOUNT} rows left to delete"
          if [ ${AMOUNT} -lt 1000 ]
          then
             LIMIT=${AMOUNT}
          else
             LIMIT=1000
          fi
          QUERY="delete low_priority from pricedata where pricedata > '20120413' limit ${LIMIT};"
          ${MYSQL} -u ${MYSQL_USER} -p${MYSQL_PWD} -e "${QUERY}" ${DB}
          STATUS=$?
          if [ ${STATUS} -ne 0 ]
          then
             ${LOGGER} "Cleanup failed for ${TABLE}"
             ERROR=1
          fi
          QUERY="select count(*) from pricedata where pricedata > '20120413';"
          AMOUNT=`${MYSQL} -u ${MYSQL_USER} -p${MYSQL_PWD} -e "${QUERY}" ${DB} | tail -1`
       done
    

    你有关于
    pricedate
    的索引吗?我在发布后不久(不幸的是,在你回复之前)就放了一个索引。它还在建!幸好这是一个周末…@davej:在这么大的桌子上,这至少需要
    40
    分钟,如果你有很多列(或长
    TEXT
    或二进制列),这需要几个小时和几天。如果您没有使用InnoDB 1.1(或插件),则需要花费更多的时间。再次感谢您提供的信息。共有8个字段;“pricedate”是唯一非数字的。有,tho,2个BIGINT(20),所以我不知道这将如何考虑。事实上,我无论如何都得出去几个小时,所以我就让它跑吧。幸好这是在测试数据库上@达维:有了一台像样的服务器,大概需要一两个小时。事实上,6个小时后它还没完成,所以我就把它关掉了。然后,我尝试使用索引重新创建表,然后使用“加载数据填充…”加载表。如果没有索引,文件运行不到40分钟。有了这个指数,它在2小时15分钟内达到了负载的40%左右,并且随着时间的推移而变慢。我使用char格式作为日期字段,因为它在我的应用程序中运行良好,并且更易于加载。现在我想知道我是否应该把它改成一个实际的日期。我假设是因为数字字段更容易索引?还是更容易用作删除查询的条件?非常感谢你的洞察力。