Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.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
C# 使用TransactionScope处理MySQL和读锁_C#_Mysql_Subsonic_Transactions_Transactionscope - Fatal编程技术网

C# 使用TransactionScope处理MySQL和读锁

C# 使用TransactionScope处理MySQL和读锁,c#,mysql,subsonic,transactions,transactionscope,C#,Mysql,Subsonic,Transactions,Transactionscope,我有以下情况: 如果我有一个MySQL数据库和一个InnoDB表,我用它来存储唯一的数字。 我启动一个事务,读取值(例如1000471),将该值存储在另一个表中,并更新递增的值(100472)。现在我想避免在我的事务运行时,其他人甚至读取该值 如果我使用纯MySQL,我会这样做: 例外(“锁定tbl1读取”) 执行(“从tbl1中选择…”) 执行(“插入tbl2”) 执行(“解锁表”) 但是由于我使用亚音速作为DAL,并且代码应该独立于mysql,所以我必须使用TransactionScope

我有以下情况:

如果我有一个MySQL数据库和一个InnoDB表,我用它来存储唯一的数字。 我启动一个事务,读取值(例如1000471),将该值存储在另一个表中,并更新递增的值(100472)。现在我想避免在我的事务运行时,其他人甚至读取该值

如果我使用纯MySQL,我会这样做:

例外(“锁定tbl1读取”)
执行(“从tbl1中选择…”)
执行(“插入tbl2”)
执行(“解锁表”)

但是由于我使用亚音速作为DAL,并且代码应该独立于mysql,所以我必须使用TransactionScope

我的代码:

        TransactionOptions TransOpt = new TransactionOptions();
        TransOpt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
        TransOpt.Timeout = new TimeSpan(0, 2, 0);

        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, TransOpt))
        {

             // Select Row from tbl1

             // Do something

             ts.Complete();
        }
根据TransactionOptions的帮助

我想要达到的效果可以通过IsolationLevel.ReadCommitted实现,但我仍然可以从事务外部读取行(如果我尝试更改它,我会得到一个锁,因此事务可以工作)


有人有什么建议吗?使用TransactionScope是否也可以进行读取锁定?我的第一个猜测是使用
选择进行更新,在快速搜索之后,我在MySQL 5参考中找到了一个关于的页面


如果我理解正确,这与使用的隔离级别无关。注意——隔离级别只是告诉当前事务如何受到其他事务更改的影响。它不告诉其他事务可以做什么。但是,更高的隔离级别需要更多的限制锁。

我的第一个猜测是使用
SELECT for UPDATE
,在快速搜索之后,我在MySQL 5参考中找到了一个关于的页面


如果我理解正确,这与使用的隔离级别无关。注意——隔离级别只是告诉当前事务如何受到其他事务更改的影响。它不告诉其他事务可以做什么。但是,更高的隔离级别需要更多的限制锁。

因为我没有找到一种方法来锁定一行,以便使用InnoDB和TransactionScope进行读取(我可能错了),这应该可以工作:

如果我同时运行两个事务(没有TransactionOptions),其中一个事务完成,那么另一个事务由于“死锁”异常而无法完成

根据MySQL的说法,最好的做法不是避免这种异常,而是期望出现死锁并重新启动事务

如果设置:

    TransactionOptions TransOpt = new TransactionOptions();
    TransOpt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

对于您的事务,您不会得到死锁异常,但在我的情况下,这将导致一个复杂的唯一数字,这更糟糕。

由于我没有找到一种方法来锁定一行,以便使用InnoDB和TransactionScope进行读取(我可能错了),这应该可以工作:

如果我同时运行两个事务(没有TransactionOptions),其中一个事务完成,那么另一个事务由于“死锁”异常而无法完成

根据MySQL的说法,最好的做法不是避免这种异常,而是期望出现死锁并重新启动事务

如果设置:

    TransactionOptions TransOpt = new TransactionOptions();
    TransOpt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

对于您的事务,您不会遇到死锁异常,但在我的情况下,这将导致一个复杂的唯一数字,更糟糕。

如果有人感兴趣,这就是TransactionOptions对MySql的影响:

假设我有两种方法

Method1启动一个事务,从我的表中选择一行,增加值并更新表

方法2是相同的,但在选择和更新之间,我增加了1000毫秒的睡眠时间

现在假设我有以下代码:

    Private Sub Button1_Click(sender as Object, e as System.EventArgs) Handles Button1.Click

        Dim thread1 As New Threading.Thread(AddressOf Method1)
        Dim thread2 As New Threading.Thread(AddressOf Method2)

        thread2.Start() // I start thread 2 first, because this one sleeps
        thread1.Start()

    End Sub
如果没有事务,则会发生这种情况:
thread2启动,读取值5,然后休眠,
thread1启动,读取值5,将值更新为6,
thread2也将该值更新为6

效果:我有两次唯一的数字

我想要的:
thread2启动,读取值5,然后休眠,
thread1启动,尝试读取值,但获得锁并休眠,
thread2将值更新为6,
thread1继续,读取值6,将值更新为7

这就是如何使用TransactionScope启动事务:

        TransactionOptions Opts = new TransactionOptions();
        Opts.IsolationLevel = IsolationLevel.ReadUncommitted;

        // start Transaction
        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, Opts))
        {
            // Do your work and call complete
            ts.Complete();
        }
它甚至可以管理分布式事务。如果抛出异常,则永远不会调用ts.Complete,并且作用域的Dispose()部分回滚事务

以下是不同隔离级别如何影响事务的概述:

  • 隔离级别。混乱
    抛出NotSupportedException-不支持混沌隔离级别

  • 隔离级别。重新提交 事务不会相互干扰(两次相同的读取,错误)

  • IsolationLevel.ReadUncommitted
    事务不会相互干扰(两次相同的读取,错误)

  • 隔离级别。可重复读取 事务不会相互干扰(两次相同的读取,错误)

  • 隔离级别.可序列化
    尝试获取锁时抛出MySqlException-Deadlock;在更新期间尝试重新启动事务

  • 隔离级别。快照
    抛出MySqlException-您的SQL语法中有错误;检查与您的MySQL服务器版本对应的手册,了解在连接过程中在第1行的“”附近使用的正确语法。Open()

  • 隔离级别。未指定 尝试获取锁时抛出MySqlException-Deadlock;在更新期间尝试重新启动事务

  • 未设置交易选项
    尝试获取锁时抛出MySqlException-Deadlock;在更新期间尝试重新启动事务


如果有人感兴趣,这就是TransactionOptions对MySql的影响:

假设我有两种方法

Method1启动一个事务,从我的表中选择一行,增加值并更新表

方法2相同,但在选择
        // start transaction
        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
        {
            using (SharedDbConnectionScope scope = new SharedDbConnectionScope(DB._provider))
            {

                try
                {

                    Record r = new InlineQuery().ExecuteAsCollection<RecordCollection>(
                        String.Format("SELECT * FROM {0} WHERE {1} = ?param FOR UPDATE",
                                        Record.Schema.TableName,
                                        Record.Columns.Column1), "VALUE")[0];

                    // do something

                    r.Save();
                 }
             }
         }