zer*_*r09 16 mysql innodb transaction locking
我之前没有尝试过使用 MySQL 事务,我只是想澄清一些事情。
如果两个用户在非常准确的时间执行查询,MySQL 将如何处理?例如,用户正在尝试更新记录。
user1:更新表集 column = column - 4 where column_id = 1;
user2:更新表集 column = column - 7 where column_id = 1;
现在,如果我使用事务,MySQL 是否会选择首先执行哪个查询并锁定第二个用户,直到提交第一个查询?那是表锁还是行锁?
如果第三个用户将发出 select 语句怎么办?MySQL 将返回的值是什么?
PS 这将在 Innodb 上。
Ric*_*mes 21
像这样的单个语句对于 MyISAM 或 InnoDB、事务或 autocommit=ON 的工作方式相同。它阻塞足以执行查询,从而阻塞其他连接。完成后,另一个连接继续。在所有情况下,该列很快就会减少 11。
第三个用户可能会看到值减少了 0 或 4 或 7 或 11。“非常精确的时间”实际上是不可能的,因为在执行每个语句的某个时刻,会检查/设置/设置单线程锁. 也就是说,它们会被序列化,速度快到你看不到。
InnoDB 只锁定行,而不锁定表。(好吧,DDL 语句做更粗的锁。)
更有趣的是一个交易修改了两件事,或者花费了大量时间:
意向案例:单个项目但需要时间:
BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
选择需要这样写:
SELECT something FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
这告诉其他连接“我打算更新该行;请不要把我搞砸”。(我举了这个例子,因为很多新手都忽略了这个微妙之处。)
死锁案例: 搞砸了两件事:
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;
Run Code Online (Sandbox Code Playgroud)
这是僵局的典型例子——每个人抓住一件东西,然后伸手去拿另一件东西。显然它不能工作。一笔交易被杀死;另一个完成。因此,您必须检查错误,以便您可以发现它。
对死锁的正常反应是重放整个失败的事务。到那时,另一个连接将不会受到干扰,它应该可以顺利进行。(好吧,另一个连接可能会造成另一个死锁。)
延迟案例:如果两个连接以相同的顺序抓取多个东西,那么一个可以延迟到另一个完成。为了避免“永远等待”,有一个默认的 50-second innodb_lock_wait_timeout。你的一对简单UPDATEs实际上就是这种情况的一个例子。一个会很快完成;另一个停止直到第一个完成。
注意死锁是如何(在某些情况下)通过对你接触的东西进行一致排序而变成延迟的。
自动提交= 1: 通过此设置和不调用BEGIN,每个语句实际上是:
BEGIN;
your statement
COMMIT;
Run Code Online (Sandbox Code Playgroud)
autocommit=0: 这是等待发生的麻烦。执行写入查询时,BEGIN会隐式生成 a。但是,您有责任最终发布COMMIT. 如果你不这样做,你会想知道为什么你的系统挂了。(另一个常见的新手错误。)我的建议:“永远不要使用=0”。
| 归档时间: |
|
| 查看次数: |
24303 次 |
| 最近记录: |