我可以在删除查询中使用 SET LOCK_TIMEOUT 吗?
Can I use SET LOCK_TIMEOUT in delete query?
我在我的办公室使用 MAMP 服务器,我有一个 table 存储了大约 75 万 (750 000) 条记录。在上传文件时,如果数据已经存在,我们不会因为任何业务逻辑而抛出错误,只是我们删除文件那个时间范围内的那些记录并从文件中重新插入数据。但是在删除的时候调试的时候会抛出lock timeout异常导致文件上传失败。我怎样才能防止这个超时?锁定超时可以用于我们保存在属性文件中的删除查询吗?
查询:
DELETE * FROM TABLE_NAME WHERE DATE >= (STARTDATE) AND DATE <= (EndDate).
比如说,至少有 10k 条记录必须删除,这些记录可能属于这些日期范围。以上查询给出锁超时异常。
在大型 table 上执行像您这样的批量操作可能非常耗时。为什么?
- 服务器可能很难找到正确的行。
- 单个查询(在 InnoDB 中)具有事务语义。也就是说,服务器必须能够在任何部分失败时回滚整个操作。这意味着服务器必须存储足够的数据来恢复所有删除的行,直到删除操作完成。这样做会使服务器更加努力。
- 您的应用程序的其他部分可能正在同时访问同一个 table。如果是这样,他们会等待轮到他们,您的系统会阻塞。
如何解决这个问题。
- 确保您的列上有一个名为
DATE
的索引,以便服务器可以有效地找到正确的行。
- 如果您的应用程序的其他部分查询数据库,请将此语句放在 SELECT 语句之前。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
。这告诉查询它可以继续,即使它可能会得到一个即将被删除的行。
- 最佳选择:批量删除。这样做:
DELETE * FROM TABLE_NAME WHERE DATE >= (STARTDATE) AND DATE <= (EndDate) LIMIT 1000;
并重复删除操作,直到它处理零行。它使用多个事务,同时将每个事务保持在合理的大小,这样服务器就不会被它们阻塞。
这种事情可以在 java 中用像这样的伪代码这样的循环最简单地完成。
bool done = false;
while (!done) {
int rowcount = execute.Update("Delete Query with LIMIT clause");
if (rowcount <= 0) done = true;
}
我在我的办公室使用 MAMP 服务器,我有一个 table 存储了大约 75 万 (750 000) 条记录。在上传文件时,如果数据已经存在,我们不会因为任何业务逻辑而抛出错误,只是我们删除文件那个时间范围内的那些记录并从文件中重新插入数据。但是在删除的时候调试的时候会抛出lock timeout异常导致文件上传失败。我怎样才能防止这个超时?锁定超时可以用于我们保存在属性文件中的删除查询吗?
查询:
DELETE * FROM TABLE_NAME WHERE DATE >= (STARTDATE) AND DATE <= (EndDate).
比如说,至少有 10k 条记录必须删除,这些记录可能属于这些日期范围。以上查询给出锁超时异常。
在大型 table 上执行像您这样的批量操作可能非常耗时。为什么?
- 服务器可能很难找到正确的行。
- 单个查询(在 InnoDB 中)具有事务语义。也就是说,服务器必须能够在任何部分失败时回滚整个操作。这意味着服务器必须存储足够的数据来恢复所有删除的行,直到删除操作完成。这样做会使服务器更加努力。
- 您的应用程序的其他部分可能正在同时访问同一个 table。如果是这样,他们会等待轮到他们,您的系统会阻塞。
如何解决这个问题。
- 确保您的列上有一个名为
DATE
的索引,以便服务器可以有效地找到正确的行。 - 如果您的应用程序的其他部分查询数据库,请将此语句放在 SELECT 语句之前。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
。这告诉查询它可以继续,即使它可能会得到一个即将被删除的行。 - 最佳选择:批量删除。这样做:
DELETE * FROM TABLE_NAME WHERE DATE >= (STARTDATE) AND DATE <= (EndDate) LIMIT 1000;
并重复删除操作,直到它处理零行。它使用多个事务,同时将每个事务保持在合理的大小,这样服务器就不会被它们阻塞。
这种事情可以在 java 中用像这样的伪代码这样的循环最简单地完成。
bool done = false;
while (!done) {
int rowcount = execute.Update("Delete Query with LIMIT clause");
if (rowcount <= 0) done = true;
}