锁定以处理并发 - 一个好主意?

Gra*_*ton 5 database-design locking

为了处理并发问题,是锁定 - 任何形式的锁定,无论是行,表还是数据库锁定一个好的解决方案?

如果没有,如何处理并发问题?

Mik*_*ick 8

如果您相信Oracle,不,不相信.那是因为甲骨文竭尽全力避免它.

问题是读者可以阻止编写者和编写者阻止读者,并且作者必须等到所有读者在写完之前完成一行.这延迟了写入过程及其调用者.如果必须回滚事务,则在事务结束时保持独占锁(用于写入) - 这将阻止其他事务看到新值,直到事务提交为止.

实际上,如果没有太多争用,锁定通常很好,与任何并发编程相同.如果行/页/表的争用太多(没有很多数据库服务器进行全数据库锁定),则会导致事务依次执行而不是并发执行.

Oracle使用行版本控制,而不是锁定行来编写行,而是创建行的新版本.需要重复读取的读者会记住他们读取的行的哪个版本.但是,如果记住其读取的读取器尝试更新由另一个写入器更新的行,则会发生错误,因为此事务读取了该行; 这是为了阻止丢失的更新.为了确保您可以更新行,您必须说SELECT是FOR UPDATE; 如果你这样做,它需要一个锁 - 只有一个事务一次可以持有一行FOR UPDATE,并且冲突的事务必须等待.

SQL Server 2005及更高版本支持快照隔离,这是行版本控制的名称.同样,如果您需要更新刚刚读取的某些数据,则应该要求更新锁 - 在SQL Server中,使用WITH(UPDLOCK).

锁定的另一个问题是死锁的可能性.这就是两个事务各自对另一个需要的资源进行锁定的情况,或者通常一个事务周期持有彼此需要进行的锁定.数据库服务器通常会检测到此死锁并终止其中一个事务,将其回滚 - 然后您需要重试该操作.您有多个并发事务修改相同行的任何情况都有可能导致死锁.如果以不同的顺序触摸行,则会发生死锁; 执行数据库服务器将使用的顺序非常困难(通常您希望优化程序选择最快的顺序,不一定在不同的查询中保持一致).

一般来说,我建议与线程一样 - 使用锁定,直到您可以证明它们导致可伸缩性问题,然后找出如何使最关键的部分无锁定.