0

我有一个应用程序,它使用一个类来创建一个完整的 MySQL 数据库供应用程序使用。该类使用单独的方法来创建每个表。

对话框用于允许创建表格,因为有用于不同用途的表格以组的形式创建。每个组创建按钮的底层代码依次执行上述类中的表创建方法。

每个表创建方法使用两个查询。第一个是

DROP TABLE IF EXISTS 表名

第二个查询是表定义 CREATE TABLE ...

如果数据库为空,则表都创建成功。

如果表存在并且我从头开始重新创建表,则在尝试重新创建表时收到错误 (errno 121)。这很奇怪,因为重新创建的表中没有一个有主键,没有一个有外键!我假设 errno 121 即将出现,因为该表似乎仍然存在,即使它已被删除。

如果我使用 MySQL Workbench 手动删除表并再次运行表创建,一切都很好,并且所有表都再次成功创建。

在运行 CREATE TABLE 查询之前,DROP TABLE 查询似乎没有完成或对程序可见。DROP TABLE 最终成功,因为当我签入 MySQL Workbench 时,该表不再出现在数据库中。

我使用相同的 MySQL 命令对象来运行这两个查询。执行 DROP TABLE 查询后,我更改了 CREATE TABLE 查询的 CommandText 属性。我也尝试过使用不同的 MySQL 命令对象和不同的 MySQL 连接对象,结果相同。

知道为什么在 CREATE TABLE 查询之前没有完成或识别 DROP TABLE 查询吗?

我在 C# 的 Visual Studio 2008 中使用 MySQL Connector/NET 6.5.4 在 Windows 8 上运行 MySQL 5.1.39(在 Windows 7 上结果相同)。

按照下面 SH 的要求,这里是其中一张表(一个小表)的代码。连接字符串包含默认目录,因此我不必在查询中明确包含它。此版本将查询包装在事务中,而原始版本没有 - 相同的结果。我什至把 DoEvents 作为在黑暗中的一个镜头。

    public void CreateViewTableCasualtyLookup()
    {
        // Declare local variables.
        string strSQL = string.Empty;
        string strMsg = string.Empty;
        string strNewDBName = string.Empty;
        MySqlConnection cnNewTable = new MySqlConnection();
        MySqlCommand cmdNewTable = new MySqlCommand();
        MySqlTransaction tranNewTable = null;
        StringBuilder sbSQL = new StringBuilder();

        try
        {
            // Create a connection.
            cnNewTable.ConnectionString = m_strServerConnect;
            cnNewTable.Open();
            cmdNewTable.Connection = cnNewTable;
            tranNewTable = cnNewTable.BeginTransaction();

            // First we need to drop the exising table.
            strSQL = "DROP TABLE IF EXISTS vCasualtyLookup";
            cmdNewTable.CommandText = strSQL;
            cmdNewTable.ExecuteNonQuery();
            tranNewTable.Commit();
            Application.DoEvents();

            // Create the new table.
            tranNewTable = cnNewTable.BeginTransaction();
            sbSQL.AppendLine("CREATE TABLE vCasualtyLookup (");
            sbSQL.AppendLine("CasualtyID char(10), ");
            sbSQL.AppendLine("LookupName varchar(100)) ");
            // sbSQL.AppendLine("PRIMARY KEY (LookupName))");
            sbSQL.AppendLine(" ENGINE = InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
            cmdNewTable.CommandText = sbSQL.ToString();
            cmdNewTable.ExecuteNonQuery();
            tranNewTable.Commit();
            Application.DoEvents();
        }
        catch (Exception ex)
        {
            tranNewTable.Rollback();
            strMsg = "Application Error:\r\n";
            strMsg += "An error occurred while trying to create the view table vCasualtyLookup. ";
            strMsg += "The full text of the error is shown below:\r\n\r\n";
            strMsg += ex.Message;
            throw new ApplicationException(strMsg);
        }
        finally
        {
            // Clear objects from memory.
            if (tranNewTable != null)
            {
                tranNewTable.Dispose();
            }
            if (cmdNewTable != null)
            {
                cmdNewTable.Dispose();
            }
            if (cnNewTable != null)
            {
                if (cnNewTable.State == System.Data.ConnectionState.Open)
                {
                    cnNewTable.Close();
                }
                cnNewTable.Dispose();
            }
            if (sbSQL != null)
            {
                sbSQL = null;
            }
        }
    }       // end CreateViewTableCasualtyLookup

当执行此表和其他表的方法时,MySQL Workbench 报告 DROP TABLE 必须已完成,因为该表不再存在。当 CREATE TABLE 被执行时,它会产生一个异常:

“无法创建表casualtyutf8.vCasualtyLookup(errno 121)”

在 Locals 窗口中检查 ex 变量显示“base”错误代码为“-2147467259”,MySQL 异常“Number”为“1005”。

我刚刚检查了 MySQL 错误日志文件,它显示:

InnoDB: Warning: MySQL is trying to drop table  `casualtyutf8`.`vcasualtyassignnarratives`
InnoDB: though there are still open handles to it.
InnoDB: Adding the table to the background drop queue.

下一个条目是表已存在的 INNODB 错误。我不知道其他进程可以打开表的句柄,除非它是 Visual Studio 调试器。我关闭了应用程序并关闭了 Visual Studio,但这并没有做任何事情。

希望这可以帮助!

4

3 回答 3

0

来自评论的整理信息

问题:表没有被正确删除。删除似乎由于某种未知原因而被推迟。

Troubleshooting Methods used:
Use new MySQL Command in code -> No Change.
Break After First Drop command -> No Change
Check Mysql Logs after first Command -> Locate Error and code.
Verfiy there is no async commands lingering in code -> No Change.
Recreate Error on clean Mysql Db. -> Unrepeatable

解决方案:重新创建完整架构。错误可能是由某种 MySql Migration 引起的。

OP:信息

很明显,原始数据库的模式定义存在一些问题,因为许多表都出现了问题。当我构建我的 Windows 8 系统时,我使用 PhpMyAdmin Export 从旧的 Windows 7 环境中迁移了模式,并使用 MySQL Workbench 将它们加载到 Windows 8 中。MySQL 服务器版本在 Windows 8 和 Windows 7 上是相同的。也许在导出和导入之间有遗漏或某种故障。我永远不会知道。

于 2013-09-24T17:33:43.650 回答
0

如果您的 MySQL 服务器作为 Windows 服务运行,禁用它并从控制台运行 MySQL 服务器守护程序可能会有所帮助。

当我看到时,我遇到了一个案例:

“MySQL 正在尝试删除表Table...InnoDB:尽管它仍有打开的句柄。”

MySQL 错误日志文件中的错误。我意识到 MySQL 是作为 Windows 服务安装的,它一直处于“停止”状态。我的解决方案是重新启动 PC,这样我就可以完全禁用 Windows 服务并从控制台运行 MySQL 守护程序。

于 2013-10-28T16:02:28.070 回答
0

好的,这个属于暮光区!

SH 建议我尝试使用干净的新数据库。因此,我创建了一个新模式,并创建了数据库中存在的所有导致问题的表、视图、触发器和例程。然后,我用旧数据库中完全相同的数据填充了新数据库中的所有表。这一切都是通过我的应用程序的功能完成的。

我运行了导致新数据库出现一致问题的代码,一切正常。我可以运行代码来重建表格,但从未收到错误。我还能够运行更新对话框来更改选定的表以毫无问题地添加新列。

为了完整起见,我删除了原始模式,并以与新测试模式相同的方式从头开始重新创建它以及所有表、视图、触发器和例程,并将数据从测试表中复制回来。一切都再次运行良好,我不能再产生任何错误。

很明显,原始数据库的模式定义存在一些问题,因为许多表都出现了问题。当我构建我的 Windows 8 系统时,我使用 PhpMyAdmin Export 从旧的 Windows 7 环境中迁移了模式,并使用 MySQL Workbench 将它们加载到 Windows 8 中。MySQL 服务器版本在 Windows 8 和 Windows 7 上是相同的。也许在导出和导入之间有遗漏或某种故障。我永远不会知道。

现在一切正常,我感谢 SH 的意见和建议。

我会把这个和总是导致 BSOD 的 Word 文档放在一起——即使对于微软来说也是如此!以及在我们删除用户 ID 666 之前会导致 BSOD 的 Oracle 数据库!以及一直返回错误结果的类,直到我将它完全复制到它返回正确结果的新类中!

于 2013-09-18T16:48:19.640 回答