2

在当今时代,事务性编程是现代开发的主要内容。并发性和容错性对于应用程序的寿命至关重要,因此,事务逻辑已变得易于实现。但是,随着应用程序的增长,事务代码似乎对应用程序的可伸缩性变得越来越沉重,当您桥接分布式事务和镜像数据集时,问题开始变得非常复杂。我很好奇,在数据大小或应用程序复杂性方面,事务经常开始成为问题的根源(导致超时、死锁、关键任务代码中的性能问题等),这些问题的修复、故障排除更麻烦或解决方法,而不是设计一个本身更容错的数据模型,或使用其他方式确保数据完整性。此外,哪些设计模式可以最大限度地减少这些影响或使标准事务逻辑过时或成为非问题?

--

编辑:到目前为止,我们已经得到了一些质量合理的答案,但我想我会自己发布一个答案,以提出我听说过的一些事情,试图激发一些额外的创造力;我得到的大部分回应都是对这个问题的悲观看法。

另一个重要的注意事项是,并非所有死锁都是由于程序编码不当造成的。有时,任务关键型操作依赖于不同顺序的相似资源,或者不同查询中的复杂连接相互叠加;这是一个有时似乎不可避免的问题,但我一直参与重新设计工作流程,以促进不太可能导致问题的执行顺序。

4

5 回答 5

2

我认为没有设计模式本身可以解决这个问题。良好的数据库设计、良好的存储过程编程,尤​​其是学习如何保持交易简短,将缓解大多数问题。但是,没有 100% 保证没有问题的方法。

不过,在我职业生涯中基本上遇到的每一种情况下,死锁和减速都是通过修复存储过程来解决的:

  • 确保访问所有表以防止死锁
  • 修复索引和统计信息使一切变得更快(因此减少了死锁的机会)
  • 有时并没有真正需要交易,它只是“看起来”像它
  • 有时可以通过在单个语句中创建多个语句存储过程来消除事务。
于 2008-09-17T21:30:26.680 回答
2

从长远来看,使用共享资源是错误的。因为通过重用现有环境,您正在创造越来越多的可能性。只需回顾一下忙碌的海狸 :) Erlang 的方式是生成容错且易于验证的系统的正确方式。

但是事务性内存对于广泛使用的许多应用程序来说是必不可少的。例如,如果您咨询一家拥有数百万客户的银行,您不能仅仅为了效率而复制数据。

我认为单子是一个很酷的概念来处理改变状态的困难概念。

于 2008-09-17T21:34:08.700 回答
0

One approach I've heard of is to make a versioned insert only model where no updates ever occur. During selects the version is used to select only the latest rows. One downside I know of with this approach is that the database can get rather large very quickly.

I also know that some solutions, such as FogBugz, don't use enforced foreign keys, which I believe would also help mitigate some of these problems because the SQL query plan can lock linked tables during selects or updates even if no data is changing in them, and if it's a highly contended table that gets locked it can increase the chance of DeadLock or Timeout.

I don't know much about these approaches though since I've never used them, so I assume there are pros and cons to each that I'm not aware of, as well as some other techniques I've never heard about.

I've also been looking into some of the material from Carlo Pescio's recent post, which I've not had enough time to do it justice unfortunately, but the material seems very interesting.

于 2008-09-19T16:24:23.023 回答
0

如果您在这里谈论“云计算”,答案是将每个事务本地化到它在云中发生的地方。

整个云不需要保持一致,因为这会降低性能(如您所述)。简单地说,跟踪更改的内容和位置,并在更改通过系统传播时处理多个小事务。

用户 A 更新记录 R 而云另一端的用户 B (尚未)看到它的情况与用户 A 在当前严格事务环境中尚未进行更改时的情况相同。这可能会导致更新繁重的系统出现差异,因此系统的架构应该尽可能少地处理更新——将事物转移到数据聚合中,并在确切数字至关重要时提取聚合(即移动一致性要求从写入时间到关键读取时间)。

好吧,只是我的POV。在这种情况下,很难想象一个与应用程序无关的系统。

于 2008-09-17T21:36:14.670 回答
0

尝试以尽可能少的指令在数据库级别进行更改。

一般规则是尽可能少地锁定资源。在 Oracle 上使用 T-SQL、PLSQL、Java 或任何类似方式可以减少每个事务锁定共享资源的时间。事实上,数据库中的事务通过行级锁、多版本和其他类型的智能技术进行了优化。如果您可以在数据库中进行交易,则可以节省网络延迟。除了 ODBC/JDBC/OLEBD 等其他层。

有时程序员试图获取数据库的优点(它是事务性的、并行的、分布式的),但保留数据的缓存。然后他们需要手动添加一些数据库功能。

于 2008-09-17T22:52:21.320 回答