如何在c#代码里开启事务

为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:

【TiDB 版本】4.0

【问题描述】您好,我现在在评估tidb,编程语言是dotnet core通过MySqlConnector来链接到tidb,然后开启事务失败,后来查资料似乎jdbc也会失败,因为不支持XA?那么请问如何在代码里开启事务呢?是否有c#版本的代码参考。如果没有java版的也可以。谢谢!


若提问为性能优化、故障排查类问题,请下载脚本运行。终端输出的打印结果,请务必全选并复制粘贴上传。

事务的使用方式与 mysql 是兼容的,开启事务失败具体是什么报错呢

报以下错误:You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 2 near “XA START ‘482e16cf-7c24-4130-b281-50f16907ffd6:1’, ‘1’;”

c#关键代码如下:
TransactionOptions tsOption = new TransactionOptions();
tsOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
using (var scope = new TransactionScope(TransactionScopeOption.Required, tsOption, TransactionScopeAsyncFlowOption.Enabled))
{
try
{
string url = “Data Source=192.168.9.111;Initial Catalog=msuser;Port=4000;User ID=root;Password=123456;ConnectionReset=false;Max Pool Size=1000;”;
using (MySqlConnection conn = new MySqlConnection(url))
{
try
{
await conn.OpenAsync(); //在这句话报上面的 “XA START” SQL语法错误
}
catch (Exception ex) {
throw ex;
}

我再次做了调试,具体如下:使用c#里最常见的两个类库分别去链接mysql和tidb。发现MySql.Data.MySqlClient.MySqlConnection的都可以成功起事务,MySql.Data.MySqlClient.MySqlConnection的Mysql可以起事务,而tidb则报事务语法错误。

代码如下:
TransactionOptions tsOption = new TransactionOptions();
tsOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
using (var scope = new TransactionScope(TransactionScopeOption.Required, tsOption, TransactionScopeAsyncFlowOption.Enabled))
{
try
{
//string url = “Data Source=192.168.9.111;Initial Catalog=msuser;Port=4000;User ID=root;Password=123456;Max Pool Size=1000;”;
string url = “Data Source=192.168.9.211;Initial Catalog=msuser;Port=3306;User ID=root;Password=123456;Max Pool Size=1000;”;
using (MySql.Data.MySqlClient.MySqlConnection conn = new MySql.Data.MySqlClient.MySqlConnection(url))
{
try
{
await conn.OpenAsync(); //无论是mysql还是tidb都可以成功

                    }
                    catch (Exception ex) {
                        throw ex;
                    }
                    
                }

                using (MySqlConnector.MySqlConnection conn = new MySqlConnector.MySqlConnection(url))
                {
                    try
                    {
                        
                        await conn.OpenAsync(); //这里只有mysql成功连tidb就报事务语法错误

                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }

                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            //throw new Exception("un known");
            

            scope.Complete();
        } // scope.Dispose()

XA START 跨库/集群的分布式事务用法,tidb 不支持这种语法,因为 TiDB 可以水平扩容,没有必要支持不同集群的分布式事务,TiDB 中分布式事务是解决单个事务内操作多行数据时,底层多个存储节点的一致性问题,用于保证事务的 ACID ,这个对于应用来说是透明的。

我又换了一种写法发现可以。根据您的回复,我理解不同的代码发起了不同级别的事务。
下面这段代码可以:
using (MySqlConnector.MySqlConnection conn = new MySqlConnector.MySqlConnection(url))
{
try
{

                await conn.OpenAsync();
                MySqlConnector.MySqlCommand myCommand = conn.CreateCommand();
                var tran = await conn.BeginTransactionAsync(System.Data.IsolationLevel.ReadCommitted,default);
                
                myCommand.Transaction = tran;

而下面这段就不可以:
TransactionOptions tsOption = new TransactionOptions();
tsOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

        using (var scope = new TransactionScope(TransactionScopeOption.Required, tsOption, TransactionScopeAsyncFlowOption.Enabled))
        {

我是不是可以理解为第二段代码发起了跨库的分布式事务所以导致了事务失败,而第一端代码只起了本地事务语法,所以事务成功。

我已找到解决方案:在MySqlConnection的链接字符串里增加"UseXaTransactions=false"

:+1:

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。