在事务中锁定表

3

我希望能够在 "beginTransaction" 和结束的 "commit" 或 "rollback" 之间锁定整个表,以防止任何插入或更新操作。

我知道开始事务会导致隐式 UNLOCK TABLES 并且 LOCK table 会导致隐式 COMMIT... 那么有没有办法做到我想要的呢?


1
为什么要这样做呢?事务的整个目的在于使数据库可以进行并发操作。 - Lightness Races in Orbit
@Tomalak Geret'kal 我只是想确认在选择 TABLE A 和选择 TABLE B 之间,TABLE B 中没有插入操作。 - Flavien
3个回答

2

为什么?也许您已经忽略了事务的要点。

如果您使用可重复读取的事务隔离级别,插入、更新等操作可以在您的事务期间发生,但是您将无法看到它们。因此,就您的进程而言,表格被锁定用于插入/更新。除非它们仍在发生,它们仍然持久到磁盘,并且其他进程可以继续运行。

在您进行第一次“选择”之后,会创建一个快照,并且您实际上正在读取该快照,而不是最新版本。如果这是您想要的,请使用可重复读取。


嘿,感谢解释。实际上我并没有完全理解那个。所以正如@Luis Siquot建议的那样,在我的事务的最开始,我放置了这个select count(*) from table,之后我就能够在这个“快照”中随时选择了。 - Flavien
实际上,快照会在需要时自动开始;通常无需显式启动。一旦从InnoDB表中读取,快照就会开始。如果您真的想要,可以使用“具有一致性快照的START TRANSACTION”立即启动一个快照。 - MarkR
非常清楚(我不知道),但是,在START TRANSACTION WITH CONSISTENT SNAPSHOT之后,我认为您必须执行SELECT COUNT(*) FROM TABLE才能将TABLE添加到快照中?或者START TRANSACTION WITH CONSISTENT SNAPSHOT会锁定入口DB(s)? - Saic Siquot
不,您不需要向快照中“添加”任何表格;一旦开始,它对所有表格都是一致的。通常情况下,您也不需要使用WITH CONSISTENT SNAPSHOT。SELECT COUNT(*)通常是一个非常低效的查询,如果没有必要(在大型表格上),应该避免使用。 - MarkR

1
select count(*) from table  

在事务中,锁定msSQL 2000上的表


这并不是必需的;它不会锁定表格,任何其他查询也会启动快照(在可重复读事务隔离中)。在Innodb中,SELECT在可重复读事务隔离中从不创建锁。 - MarkR

-1
如果您正在使用PHP,那么在进行交易时,您可以设置一个SESSION变量来告诉脚本不要对数据库进行任何操作,即$_SESSION['on_going_transaction'] = true
当交易完成后,只需销毁SESSION变量,以便进行另一笔交易。这样会更容易些。

1
此解决方案不是线程安全的。在完全不同的会话中(或根本没有会话),脚本可能会在一个会话的“on_going_transaction”变量被设置时进行数据库修改。 - Asaph
是的,我的问题在于可能会有多个线程同时运行,因此我必须确保在我运行事务时没有其他线程可以对特定表进行插入操作。 - Flavien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接