我之前没有尝试过使用MySQL事务,我只想澄清一些事情.
如果两个用户在非常准确的时间执行查询,MySQL将如何处理这个问题?
例如用户正在尝试更新记录.
user1:update table set column = column – 4其中column_id = 1;
user2:update table set column = column – 7其中column_id = 1;
现在如果我使用事务,MySQL会选择首先执行哪个查询并锁定第二个用户,直到提交第一个查询为止?那会是表锁还是行锁?
如果第三个用户发出select语句怎么办? MySQL会回归的价值是什么?
附:这将是Innodb.
解决方法:
像这样的单个语句与MyISAM或InnoDB一样,使用事务或使用autocommit = ON.它阻塞足以进行查询,从而阻止其他连接.完成后,另一个连接继续.在所有情况下,该列很快会减少11.
第三个用户可能会看到值减少0或4或7或11.“非常准确的时间”实际上是不可能的,因为在执行每个语句的某个时刻,检查/设置单线程锁定/无论如何.也就是说,它们会被序列化,速度太快,你无法看到它.
InnoDB只锁定行,而不是表. (好吧,DDL语句做更大胆的锁定.)
更有趣的是一个修改两件事的事务,或者需要花费大量时间的事务:
意图案例:单项但需要时间:
BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;
因此需要编写选择:
SELECT something FOR UPDATE;
这告诉其他连接“我打算更新这行;请不要搞砸我”. (我提出这个例子,因为很多新手都错过了这个微妙之处.)
僵局案例:弄乱两件事:
BEGIN; -- in one connection
UPDATE thing_1;
UPDATE thing_2;
COMMIT;
BEGIN; -- in another connection, at the "exact same time"
UPDATE thing_2;
UPDATE thing_1;
COMMIT;
这是一个死锁的经典例子 – 每个人抓住一件事然后到达另一件事.显然它无法发挥作用.一笔交易被杀;另一个完成.因此,您必须检查错误,以便发现它.
对死锁的正常反应是重放整个失败的事务.到那时,另一个连接不会干扰,它应该没有麻烦. (好吧,另一个连接可能会造成另一个死锁.)
延迟情况:如果两个连接以相同的顺序抓取多个内容,则可以延迟一个直到另一个完成.为了防止“永远等待”,默认的50秒innodb_lock_wait_timeout.你的一对简单UPDATE实际上是这种情况的一个例子.一个人会很快完成;另一个停滞直到第一个结束.
请注意,通过不断地对您触摸的内容进行排序,可以将死锁(在某些情况下)转换为延迟.
autocommit = 1:使用此设置并且不调用BEGIN,每个语句都是有效的:
BEGIN;
your statement
COMMIT;
autocommit = 0:这是等待发生的麻烦.执行写入查询时,将隐式生成BEGIN.但是,最终发布COMMIT是您的责任.如果你没有这样做,你会想知道为什么你的系统挂起了. (另一个常见的新手bug.)我的建议是:“永远不要使用= 0”.