Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 有没有比交易更有效的方法?_Php_Mysql_Transactions - Fatal编程技术网

Php 有没有比交易更有效的方法?

Php 有没有比交易更有效的方法?,php,mysql,transactions,Php,Mysql,Transactions,上述操作将某些内容插入表1,如果成功,则更新表2的计数字段 当然,这类事情可以由事务处理,但是事务需要锁定表,这在高并发系统中是没有效率的。如果您需要在该事务中更新多个表,情况可能会更糟 你的解决方案是什么 我使用的是PHP,我通过以下方式实现事务: insert into table1 ...; update table2 set count=count+1; 所以看起来那些$statement中引用的所有表都将被锁定?在我看来,这些表更像是一个“触发器”作业。onInsert执行某些操作。

上述操作将某些内容插入
表1
,如果成功,则更新
表2
计数
字段

当然,这类事情可以由事务处理,但是事务需要锁定表,这在高并发系统中是没有效率的。如果您需要在该事务中更新多个表,情况可能会更糟

你的解决方案是什么

我使用的是PHP,我通过以下方式实现事务:

insert into table1 ...;
update table2 set count=count+1;
所以看起来那些
$statement
中引用的所有表都将被锁定?

在我看来,这些表更像是一个“触发器”作业。onInsert执行某些操作。

事务(在
MySQL
上下文中假定
InnoDB
)不需要锁定整个表

INSERT
将在不使用间隙锁的情况下锁定单个行

如果在
WHERE
子句中的索引字段上提供相等或
IN
条件,则
UPDATE
也不会锁定任何间隙

这意味着,对于索引正确的表,
插入项
不会相互阻止,而
更新项
只会在它们影响同一行时相互阻止

UPDATE
当然会锁定它影响的单个行,但由于它是事务中的最后一个操作,因此在提交操作后会立即解除锁定


实际上,需要锁定本身,以便两个并发更新将按顺序增加计数。

使用InnoDB存储引擎。它是行级锁定,而不是MyISAM,后者是表级锁定。

事务对于确保“要么全有,要么全无”的行为非常重要——即使系统中存在高负载或高并发性,您也不应该停止使用事务,至少在您需要数据保持一致的情况下是如此


(并且事务不一定会锁定整个表)

事务不一定会请求锁定整个表

此外,InnoDB使用不同的锁定策略支持不同的翻译隔离级别。您可能需要检查:


如果速度至关重要,我可能会尝试将更新计数缓存在内存中(使用线程安全代码),并且只定期将其写回数据库。当我这样做时,我肯定会使用事务。这样做的缺点是,您需要愿意将计数视为唯一近似值。如果您需要它对于一个操作是绝对正确的,那么需要在事务中重新计算它


正如其他人指出的,使用支持行级锁定的数据库和简单地使用显式(或通过触发器隐式)事务可能更容易。它肯定更准确、更安全。

或者您可以切换到Oracle,它(在大多数情况下)不执行锁定。:)
@LBushkin
:在
Oracle
中对永久表执行的任何
DML
操作都会锁定受影响的行,直到事务结束。Oracle将在相关的位置锁定行-这是获得正确事务行为所必需的。哪个版本的MySQL实现了稳定的触发器?插入操作可能不会相互阻塞行锁,但它们仍然可以与表中索引上的锁竞争,实际上,它们之间会发生死锁。我已经看过了。
@MarkR
:你是对的,这就是为什么我特别提到“正确索引的表”。这里有一个关于你正在谈论的问题的问题:
mysql_query('begin');

mysql_query($statement1);

mysql_query($statement2);
...
mysql_query('commit');