我有以下两个交易(这是我正在尝试解决的旧考试问题)。我需要不使用commit,rollback或insert into 在事务A和B中获得相同的输出 我设法通过添加
来做到这一点REPLACE INTO T
SELECT 10,10 FROM dual;
红色文字(标有“(1)”) 它工作但我想知道是否有任何其他方式,如改变隔离级别或做一些更棘手的事情? 此外,是否有来自事务B的命令我们可以删除它并仍然得到相同的结果? https://i.imgur.com/Ba9jLOz.png
答案 0 :(得分:0)
根据您的评论,您只能在红色虚线处发出命令。根据您的评论,我还假设innodb表引擎与默认的可重复读取隔离模式一起使用。
以上意味着无法使用更改事务隔离级别,因为显然您cannot change the isolation level of an ongoing transaction。
这也意味着您需要一个语句,向表中添加一条记录,以补偿事务B运行时由事务A添加的id=5
记录。这个问题排除了insert
,所以这真的让你留下replace
,因为它是唯一可以在表格中创建新记录的其他语句。
还有另一种偷偷摸摸的解决方案。发出
update t set b=1 where id=5;
并且计数将匹配。原因是一致快照适用于仅选择but not to changes to data。上述语句将使用id=5
更新记录,从而将其带入快照:
数据库状态的快照适用于事务中的SELECT语句,不一定适用于DML语句。如果插入或修改某些行然后提交该事务,则从另一个并发REPEATABLE READ事务发出的DELETE或UPDATE语句可能会影响那些刚刚提交的行,即使会话无法查询它们。如果事务确实更新或删除了由其他事务提交的行,则这些更改将对当前事务可见。
此外,如果您在事务B中删除select
之前的insert
,则应该得到相同的结果,而不会在红色虚线上添加任何内容。一致快照由第一次读取建立。通过删除提到的select,将在事务A提交后建立快照,因此事务B可以看到它的更改。