为了处理并发问题,是锁定 - 任何形式的锁定,无论是行,表还是数据库锁定一个好的解决方案?
如果没有,如何处理并发问题?
答案 0 :(得分:8)
如果你相信甲骨文,不,不相信。这是因为甲骨文竭尽全力避免它。
问题在于读者可以阻止编写者和编写者阻止读者,并且作者必须等到所有读者在写完之前完成一行。这延迟了写入过程及其调用者。如果必须回滚事务,则在事务结束时保留独占锁(用于写入) - 这将阻止其他事务看到新值,直到事务提交为止。
实际上,如果没有太多争用,锁定通常很好,与任何并发编程相同。如果行/页/表的争用太多(没有很多数据库服务器进行全数据库锁定),它将导致事务依次执行而不是并发执行。
Oracle使用行版本控制,而不是锁定行来编写行,而是创建行的新版本。需要重复读取的读者会记住他们读取的行的哪个版本。但是,如果记住其读取的读取器尝试更新由另一个写入器更新的行,则会发生错误,因为此事务读取了该行;这是为了阻止丢失的更新。为了确保您可以更新行,您必须说SELECT是FOR UPDATE;如果你这样做,它需要一个锁 - 只有一个事务一次可以持有一行FOR UPDATE,并且一个冲突的事务必须等待。
SQL Server 2005及更高版本支持快照隔离,这是行版本控制的名称。同样,如果需要更新刚读取的一些数据,则应该要求更新锁 - 在SQL Server中,使用WITH(UPDLOCK)。
锁定的另一个问题是死锁的可能性。这就是两个事务各自对另一个需要的资源进行锁定的情况,或者通常一个事务周期持有彼此需要进行的锁定。数据库服务器通常会检测到此死锁并终止其中一个事务,将其回滚 - 然后您需要重试该操作。您有多个并发事务修改相同行的任何情况都有可能导致死锁。如果以不同的顺序触摸行,则会发生死锁;执行数据库服务器将使用的顺序非常困难(通常您希望优化程序选择最快的顺序,不一定在不同的查询中保持一致)。
一般来说,我建议使用与线程相同的方法 - 使用锁定,直到您可以证明它们导致可伸缩性问题,然后找出如何使最关键的部分无锁定。
答案 1 :(得分:2)
您必须先定义目标。如果是并发请求,您希望赢得最后一个用户或第一个用户。 数据库锁定肯定是一种糟糕的方式。尝试尽可能晚地锁定表/行并尽快释放锁。
答案 2 :(得分:1)
我认为不是,因为它一直“向下”并使您的应用程序更加复杂。大多数语言都有出色的并发处理技术,即使这样,最好的方法是编写可以“本机”处理并发的代码。
有关Java中并发性的更多信息: http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html
答案 3 :(得分:1)
数据库锁定 - 与表或行锁定相反 - 是处理并发性的一种坏方法;它排除了并发性。
答案 4 :(得分:1)
有许多合理的替代方法可以自己编写某种DMBS锁定代码。请记住,某些锁定确实总是发生(原子动作等),但关键是如果你不需要,你不想去那里。如果你不需要,你不想和哲学家一起用餐。事务是绕过锁定的一种方式,但主要用于提交。使用标记/指示记录脏的字段(脏位模式)是另一种方式,只需确保以原子访问方式这样做。该语言通常具有前面帖子所引用的合适解决方案,但是该语言通常仅支持应用程序,进程处理,级别并发性,有时在数据库中并发必须。我不想假设你有一个丰富的应用程序层,但如果你这样做,有很多抽象层可以为你处理这个问题。 TopLink by Oracle是免费的,是Hibernate中更强大的兄弟,它们通过抽象,脏位,缓存和延迟锁定来帮助您管理数据库并发性挑战。你真的不想自己实现这些,除非你正在为学校或个人项目编写代码。了解问题,但站在巨人的肩膀上。
答案 5 :(得分:0)
您的意思是在应用程序中处理并发,或者解决您在数据库中遇到的并发问题。如果是前者,它并没有把我视为一种好方法。如果是后者,如果不重新设计模式,这可能是您唯一的答案。