设为首页 - 加入收藏 PHP编程网 - PHP站长网 (http://www.52php.cn)- 电商,百科,编程,业界,移动互联,5G,云计算,站长网!
热搜: 娱乐 服务 专业 百度
当前位置: 首页 > 编程 > 正文

.NET+PostgreSQL实践与避坑指南(2)

发布时间:2021-03-14 19:15 所属栏目:[编程] 来源:脚本之家
导读:但你确定你真的用得到预处理事务吗?我看下来我们是用不到的,但为什么出现这个问题?还是我们程序写得有问题,即便你从单个方法上看不出来事务包事务。以下两种场景可能会出现预处理事务: 1,我创建了一个方法A访

但你确定你真的用得到预处理事务吗?我看下来我们是用不到的,但为什么出现这个问题?——还是我们程序写得有问题,即便你从单个方法上看不出来事务包事务。以下两种场景可能会出现“预处理事务”:

1,我创建了一个方法A访问数据库,这个方法可能会被其它方法调用,所以它有个DbConnection类型的参数,表示调用者负责打开数据库连接传递过来,而A里面开启了事务,而调用者并不知情,也开启了事务,形成预处理事务

2,这种情况更隐晦些,数据库连接字符串,如:Host=192.168.1.101; Username=postgres; Password=123456; Database=testdb; Enlist=true,在后面有个叫Enlist的参数为true,这表示这个连接在打开的时候,会自动Enlist到当前执行上下文的Transaction中去,如果当前执行上下文中打开了事务(从代码上看包含在了using(TransactionScope)中),那这个数据库连接就自动Enlist上去了,再考虑这样的场景:A方法会自己打开数据库连接去查询点什么东西,B方法也会访问数据库,且B方法会使用事务,事务中调用了A方法,A方法打开数据库连接的时候发现当前执行上下文中存在Transaction,于是自动Enlist上去了,不经意间形成了预处理事务,且还是“分布式”的(A和B打开的可能是不同的数据库连接),这种情况应该并不是你所需要的

那我们应该怎么做?下面是我的做法:

1,max_prepared_transactions还是设置为0,关掉,因为我们真用不到,如果用得到,那就是我们代码写错了,所以一旦出现“禁用已准备好的事务”这个异常,就回去检查代码

2,把Enlist=true在数据库连接字符串中去掉,这么一来,每次使用事务都需要显式地调用 conn.EnlistTransaction(Transaction.Current),虽然对了一行代码,但语义更明确,也不用考虑到底是TransactionScope包DbConnection或反过来DbConnection包TransactionScope

3,规范化我们的数据库访问代码,明确哪些是需要事务哪些是不需要的,在各个方法的注释上注明

40001:由于多个事务间的读/写依赖而无法串行访问

它对应的英文是:Cound not serialize access due to read/write dependencies among transactions,这个应该怎么理解呢?其实了解数据库事务隔离级别的人对这个应该不会陌生。.NET的TransactionScope默认使用的是事务隔离级别中的最高级别——Serializable(可序列化)。这个级别最大程度上确保了数据的一致性,但代价也挺高,一来速度较慢,二来很容易出现“事务间读/写依赖”,就是这个错误了,举个简单的例子:

A、B两个事务,同时访问test表中id为50的一条记录,A读出这条记录,接着B更新了这条记录并提交,根据可序列化的隔离级别的规则,A并不知道B更新了记录,A在B提交后尝试修改这条记录,这时候数据库就会让A事务失败,并抛出这个异常,因为让A修改成功的话,就会导致B之前的修改不经意间丢失了,可序列化隔离级别并不允许这种情况的发生。

所以,这是个“正常的错误”,按常规的业务逻辑来说,应该很少会出现,如果真的出现,且频繁出现,那需要考虑下是不是业务逻辑设计得不太合理,看看能不能从设计上避免这个问题,如果业务逻辑一定如此,那可以用下面的方法尝试一下:

1,将这种并行事务用客户端代码排个队,弄个线程安全队列,逐个执行,这样速度会慢点,但确保了每个事务都能成功

2,捕捉这个异常,然后自动重试,其实这也是数据库推荐的正统的做法

3,降低事务隔离级别,这个可能会出现问题,也可能不出现,这完全取决于你的业务,关于事务隔离级别,这是个蛮大的话题,我考虑适当时候再写一篇文章

4,对于极少出现的频次来说,可以不处理,仅仅需要捕捉这个异常类型,然后提示用户重试即可,很多网站貌似都这么干的

总结

有时间的话我会另外开一篇文章来写写PG的一些常规用法,如热备冷备还原维护等,但不太能保证什么时候能写出来。

到此这篇关于.NET+PostgreSQL实践与避坑指南的文章就介绍到这了,更多相关.NET+PostgreSQL实践与避坑指南内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:脚本之家

链接:https://www.jb51.net/article/205026.htm

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

推荐文章
热点阅读