我有一个复杂的选择查询和一个巨大的表。
我跑这个select
语句,同时一个Update
语句到达并尝试更新表。
恕我直言-更新需要排它锁-这样的更新语句将不得不等待 ,直到选择命令完成。
我对吗 ?
我该怎么才能做到:执行复杂的
select
,也让update
命令运行( 目前我不在乎脏数据 )
我有一个复杂的选择查询和一个巨大的表。
我跑这个select
语句,同时一个Update
语句到达并尝试更新表。
恕我直言-更新需要排它锁-这样的更新语句将不得不等待 ,直到选择命令完成。
我对吗 ?
我该怎么才能做到:执行复杂的select
,也让update
命令运行( 目前我不在乎脏数据 )
是 - 在一定程度上。
一多久SELECT
持有的共享锁取决于事务的隔离级别:
READ UNCOMMITTED
-没有共享锁被获取在所有- UPDATE
没有被阻塞 READ COMMITTED
-共享锁获取只是为了读取数据的持续时间- UPDATE
可能被阻塞的时间很短的时间 REPEATABLE READ
和SERIALIZABLE
-共享锁被获取并保持到直至事务结束- UPDATE
被阻塞,直到SELECT
事务端 从技术上讲, UPDATE
语句第一得到一个UPDATE
锁-其为具有共享锁(如所使用的兼容SELECT
) -供的,而它的读取行的电流值将被更新的时间的持续时间。
一旦这样做了,将Update
锁升级为独占锁定为新的数据写入到表中。
当你同时运行两个语句(一个SELECT和UPDATE)的实际行为将基本随机的。 这是因为无论是操作的是瞬发。 为了简化,考虑你的表中的列表并选择遍历该列表,每次看着一行。 更新也试图更新一行或多行。 当更新试图更新背后的SELECT则什么也不会发生(不阻止)一行,因为SELECT已经发展过更新点。 如果更新试图更新在其SELECT期待,现在该行则更新将不得不等待选择继续前进,这将发生非常非常非常快,更新将解锁并取得成功, 而选择正在向前推进。 但是,如果更新是提前选择的更新一行,则更新会成功,以及后来的SELECT最终将完全达到该行并停止,阻止。 现在选择要等到该做的UPDATE事务提交 。
这是简单的故事。 在现实生活中要复杂得多。 该SELECT可以有多个读取点(并行计划)。 无论是SELECT和UPDATE受到选择的访问路径,这意味着使用一个或多个二级索引定位行。 复杂的查询可能包含导致多个查找到一个表(例如,连接)运算符。 无论是SELECT和UPDATE可以做书签查找获取BLOB数据,这显著改变锁定行为。 基数估计可能导致SELECT以高粒度锁定模式(例如,表级共享锁)上运行。 更新可以触发锁升级,并且升级可能会失败或成功。 选择不同的访问路径可能会导致僵局 。 假锁争可能是由于哈希冲突 。 有只是一个在这个发言权无数的变量。 我甚至没有提到更高的隔离级别(可重复读,序列化)。
也许你应该使用快照隔离,不用担心这个问题?