以下假设所有语句都在带有InnoDB表的MySQL 5.6上的事务中执行。此外,col1和col2一起形成一个唯一的密钥。
如果我在会话1中执行SELECT * FROM table WHERE col1 = 1 AND col2 = 1 FOR UPDATE
,我会从该行获取数据并在该行上获得独占锁定。因此,如果我在会话2上执行相同的语句,它将等待该锁定被释放后再执行任何操作或进入超时。到目前为止,非常好。
现在假设SELECT ... FOR UPDATE
返回一个空集,我们尝试在另一个会话中插入一些内容:
-- Session 1
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM `table` WHERE `col1` = 1 AND `col2` = 1 FOR UPDATE;
Empty set (0.01 sec)
-- Do whatever else takes some time
-- Session 2
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `table` SET `col1` = 1, `col2` = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
这种行为就像我期待的那样。但是,如果我们这样做:
-- Session 1
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM `table` WHERE `col1` = 1 AND `col2` = 1 FOR UPDATE;
Empty set (0.00 sec)
-- Session 2
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM `table` WHERE `col1` = 1 AND `col2` = 1 FOR UPDATE;
Empty set (0.00 sec)
mysql> INSERT INTO `table` SET `col1` = 1, `col2` = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
现在,我真正想要的是相同(尚未存在)行上的第二个SELECT ... FOR UPDATE
将以INSERT INTO
的相同方式等待。如何在不锁定整个表的情况下实现这一点,这是不可接受的,因为其他行需要保持可访问状态。
答案 0 :(得分:0)
当您让交易运行超过几秒钟时,您就会遇到麻烦。编写代码以便更快完成。您的第一个代码示例不是<!-- tiles -->
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.tiles3.TilesViewResolver">
<property name="order" value="0" />
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<value>/WEB-INF/layout/layout.xml</value>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="1" />
<!-- View Resolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
</bean>
,默认情况下长达50秒。
您必须编写代码来捕获错误 - 例如您获得的两个不同的错误 - 并采取规避措施。该操作通常是为了启动整个事务。到那时,另一场会议很可能已经完成了它正在做的任何事情,你应该立即通过&#39;。
如果您需要一个非常长的锁定 - 例如购物车,其中用户在网页中弹跳几分钟,您必须使用其他机制来锁定&#34;而不是InnoDB&#39; s交易锁定。
如果您想进一步描述您的申请,我们可以进一步讨论。