访问数据库事务插入限制

时间:2013-11-01 11:32:32

标签: c# transactions limit ms-access-2010

在您需要提交之前或Access / Jet抛出错误之前,您可以在Access事务中执行的插入数量是否有限制?

我目前正在运行以下代码,希望确定这个最大值是多少。

OleDbConnection cn =
                new OleDbConnection(
                    @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\myAccessFile.accdb;Persist Security Info=False;");
            try
            {
                cn.Open();
                oleCommand = new OleDbCommand("BEGIN TRANSACTION", cn);               
                oleCommand.ExecuteNonQuery();    
                oleCommand.CommandText =
                            "insert into [table1] (name) values ('1000000000001000000000000010000000000000')";

                for (i = 0; i < 25000000; i++)
                {
                    oleCommand.ExecuteNonQuery();
                }                

                oleCommand.CommandText = "COMMIT";
                oleCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {

            }
            finally
            {
                try
                {

                    oleCommand.CommandText = "COMMIT";
                    oleCommand.ExecuteNonQuery();                    
                }

                catch{}

                if (cn.State != ConnectionState.Closed)
                {
                    cn.Close();
                }
            }

当我在一个未通信的事务中达到2,333,920个插入时,我在生产应用程序上收到的错误是:“文件共享锁定计数已超出。增加MaxLocksPerFile注册表项”。禁用事务修复了此问题。

2 个答案:

答案 0 :(得分:4)

我刚刚在.accdb数据库的表上成功创建并提交了5,000,000个插入事务。一个显着的区别是我没有直接发出BEGIN TRANSACTIONCOMMIT语句,而是使用OleDbTransaction对象:

cmd.CommandText =
    @"INSERT INTO Companies (ID, CompanyName) VALUES (?, ?)";
cmd.Parameters.Add("?", OleDbType.Integer);
cmd.Parameters.Add("?", OleDbType.VarWChar, 255);
cmd.Prepare();

OleDbTransaction tran =  con.BeginTransaction();
cmd.Transaction = tran;
for (int i = 1; i <= 5000000; i++)
{
    if ((i % 100) == 0)
    {
        Console.WriteLine(i.ToString());
    }
    cmd.Parameters[0].Value = i;
    cmd.Parameters[1].Value = "Company" + i.ToString();
    cmd.ExecuteNonQuery();
}
tran.Commit();

修改评论<评论

成功创建并提交10,000,000插入事务,并验证.Rollback()确实工作(好建议,neoistheone!)后,我检查了IsolationLevel交易。 ACE.OLEDB驱动程序的默认IsolationLevel显然是ReadCommitted,根据MSDN表示:

  

在读取数据时保持共享锁以避免脏读,但可以在事务结束之前更改数据,从而导致不可重复的读取或幻像数据。

维基百科很好地描述了那些不同的“阅读现象”here

也许如果我要指定更严格的隔离级别(如Serializable),我可能会遇到问题中描述的锁定限制,尽管因为这些都是INSERT操作,所以ACE.OLEDB驱动程序只需“隐藏“来自所有其他连接的插入,直到它们被提交。

编辑重新:效果

由于在事务中包装大量INSERT操作的一个相当常见的原因是为了更快地完成它们,我测试了一批包含和不包含OleDbTransaction的100,000个插入。 (在两种情况下都使用了准备好的声明。)如果没有OleDbTransaction,批处理大约需要36秒才能完成。使用默认隔离级别OleDbTransaction启用ReadCommitted会将已用时间减少到大约23秒。

答案 1 :(得分:3)

是的,实际上有一个限制。你清楚地达到了它。每Microsoft's documentation

  

如果执行事务所需的锁数超过每个文件的最大锁数,则会发生错误。

在该链接上有几个解决方法。第二个更现实,它暂时改变了最大锁。