我有一个MySql数据库,里面有九个表。我需要从C#内的异步作业动态上载到其中的六个。但是,为了加快上传速度,其中四个使用MySqlBulkLoader
,而另外两个使用手动上传方法。为了支持并发性并防止数据库中出现错误,我需要同时上载它们。为此,我决定使用事务来确保“全部或无”类型的上传。
这就是问题所在:MySqlCommand
类允许通过其MySqlTransaction
属性中的Transaction
类提供事务支持,MySqlBulkLoader
允许原子上载(我使用INNODB
作为引擎,请参见mysql - Can MySqlBulkLoader be used with a transaction?)。但是,MySqlBulkLoader
创建自己的事务用于原子上传,而另一个单独的事务将用于我将要执行的MySqlCommand
。这不支持序列化,如果一个大容量加载程序完成其作业,但应用程序在另一个加载程序完成之前关闭,则仍可能导致错误。如果事务可以嵌套,这是可以解决的;但是,它们不能:php - Mysql transactions within transactions。
我的问题如下:在C连接器中是否有任何方法允许MySqlBulkLoader
与MySqlTransaction
关联,如果没有,是否有任何方法可以自动回滚以前的MySqlBulkLoader
所做的更改。我已经查看了connector.NET 6.9提供的API,似乎这可能通过MySqlConnection.BeginTransaction()
方法实现,但来自Werner Wolf的一个问题却表明了另一种情况。
编辑
我通过this question找到了Saravanan。然而,我不认为这个问题与这个问题有关,因为MySqlBulkLoader
与MySqlCommand
混杂在一起。
最佳答案
最初的问题是:C连接器中是否存在允许MySqlBulkLoader
与MySqlTransaction
关联的方法
为此,似乎没有。仅仅将两个事务放在一起也不起作用,因为它不支持序列化(正如我所想的那样)。然而,另一个问题是:是否有任何方法可以自动回滚以前的MySqlBulkLoader
s所做的更改。
而且,似乎没有一种简单的方法来回滚更改。当然,我可以检查之前和之后的表状态,删除之前不存在的条目;但是,这个解决方案不是最优的。然而,一个解决方案可能以问题的形式出现。对原始问题的回答假定没有办法将单独的事务与MySqlBulkLoader
关联;但是没有指定我们可以自己创建一个事务(也就是说,扩展MySqlBulkLoader
类以包含Transaction
实例参数)。这似乎是问题的解决方案,也是问题Werner Wolf的解决方案。
然而,这根本不是解决办法。由于MySqlBulkLoader
是SQL的LOAD DATA INFILE
语法的一个简单包装器,所以它的作用与SQL查询一样。从MySQL Reference Manual中,我们得到了答案:本节中列出的语句(以及它们的任何同义词)隐式地结束当前会话中活动的任何事务,就像您在执行语句之前执行了提交一样。
网页下方的语句是LOAD DATA INFILE
。这是我们问题的真正答案:不可能把aMySqlBulkLoader
和aMySqlTransaction
联系起来,至少在效果上它会按照我们想要的方式工作。然而,如上所述,问题的解决方案可能是检查每个表的主键的索引,锁定表,保存它们的位置,并在上载失败后执行手动“回滚”。