Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/288.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

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 MyISAM中的事务问题_Php_Mysql - Fatal编程技术网

Php MyISAM中的事务问题

Php MyISAM中的事务问题,php,mysql,Php,Mysql,问题就在这里。我在MySQL MyISAM表中有两个表。我还有几个问题,一个问题依赖于另一个问题。这类东西: CREATE TABLE users ( name varchar(255) DEFAULT NULL PRYMARY KEY, money int(10) unsigned DEFAULT NULL ); INSERT INTO users(name, money) VALUES('user1', 700); INSERT INTO users(name, money) VAL

问题就在这里。我在MySQL MyISAM表中有两个表。我还有几个问题,一个问题依赖于另一个问题。这类东西:

CREATE TABLE users (
  name varchar(255) DEFAULT NULL PRYMARY KEY,
  money int(10) unsigned DEFAULT NULL
);
INSERT INTO users(name, money) VALUES('user1', 700);
INSERT INTO users(name, money) VALUES('user2', 200);
我需要把钱从一个用户转移到另一个用户

<?php
$query1 = "UPDATE users SET money=money-50 WHERE name = 'user1'";
$query2 = "UPDATE users SET money=money+50 WHERE name = 'user2'";

MyISAM不提供任何内部处理机制。如果需要原子性,请使用支持事务的引擎,如InnoDB引擎。这是解决这类问题的通常和公认的方法

另一种可能是存储事务,而不是总数

CREATE TABLE users(name VARCHAR(255), PRIMARY KEY (name));
CREATE TABLE transactions(from_user VARCHAR(255), to_user VARCHAR(255), amount INT);
这意味着交易现在只是一个查询,但查找当前余额更为困难

交易:

INSERT INTO transactions VALUES('user1', 'user2', 50);
找到平衡更难:

SELECT (SELECT SUM(amount) FROM transactions WHERE to_user='user2') - (SELECT SUM(amount) FROM transactions WHERE from_user='user2')
由于记录不能只插入一半,这就解决了问题。注意,我没说这是个好主意使用事务数据库。

注意:还有一种方法可以做到这一点,它相当难看,但在MyISAM中仍然应该是原子的

UPDATE users SET money=IF(name='user1',money-50, money+50) WHERE name='user1' OR name='user2';

首先,正如一些人提到的,这不是一个好主意,在任何实际系统中都不应该这样做。但我假设这是一个家庭作业,目标是找出如何在不支持原子更新的系统中伪造原子更新

您可以通过创建自己的事务日志系统来实现这一点。其思想是创建一组操作,即,如果操作被中断,您可以再次重复这些操作,并获得正确的结果。加法和减法不是幂等的,因为如果你加或减多次,你会得到不同的结果。任务是。所以你可以这样做:

CREATE TABLE transactions(
    id int auto_increment primary key,
    committed boolean default false,
    user1 varchar(255), 
    user2 varchar(255),
    balance1 int,
    balance2 int,
    index (id, committed)
);
INSERT INTO transactions(user1, user2, balance1, balance2) 
    VALUES(
        'user1', 
        'user2', 
        (SELECT money + 50 FROM users where name='user1'),
        (SELECT money - 50 FROM users where name='user2')
    );
然后,您的“事务”如下所示:

CREATE TABLE transactions(
    id int auto_increment primary key,
    committed boolean default false,
    user1 varchar(255), 
    user2 varchar(255),
    balance1 int,
    balance2 int,
    index (id, committed)
);
INSERT INTO transactions(user1, user2, balance1, balance2) 
    VALUES(
        'user1', 
        'user2', 
        (SELECT money + 50 FROM users where name='user1'),
        (SELECT money - 50 FROM users where name='user2')
    );

然后,您有一个提交事务的独立系统或函数。查找第一个未提交的事务,用存储的值更新两个帐户,并将事务标记为已提交。如果进程被中断,您将能够恢复,因为您可以回放事务,并且如果您多次回放事务,将不会造成任何伤害。

尝试
PRIMARY
而不是
PRIMARY
,它通常通过使用支持事务的后端来解决。Period.PRYMARY不是这里的重点:)而且没有办法使用支持事务的表。+1问得好,急于知道MyISAM中是否有执行安全事务的机制。将此分配给您并告诉您使用MyISAM的人显然是一个不负责任且未受过教育的人。你可能会因为这样的错误而被起诉。绝不,绝不,绝不,绝不,绝不,绝不,绝不使用MyISAM存储金融数据或转账。不管是谁告诉你你应该、必须、可以、应该——不要这样做。如果你还必须这么做,确保你有一个备份计划,当MyISAM做得最好的时候,整个功能会适得其反,击中你的脚。“更困难”?对于每一个真正使用该系统的用户来说,这将是非常缓慢的!我从来没有说过这是好的,我只是指出这是可能的。好吧,这并不是那么简单。实际上,这个“事务”集中的查询要复杂得多,只是不想用长串的查询来打扰您。这更像是检查某个数字的页面(即菜单列表中的位置)是否存在,然后所有页面都会增加,如果所有这些都完成了,我会在指向的位置添加一个新页面。还有什么更常见的方法来解决这个问题吗?@DarkFalcon这个主意不错,但是在存储了交易信息之后,我们如何真正以原子方式进行交易并更改两个帐户的余额呢?你没有。您不再存储余额,只存储对余额的更改。更新多行的语句在MyISAM中不是原子语句。在某些情况下,这仍然会失败。您能否详细说明我们如何以原子方式执行这4个步骤?:1)查找第一个未提交的事务2)更新第一个帐户3)更新第二个帐户4)将事务标记为已提交。@Pacerier存储过程可能?@DmitryScript,但除非表内部支持事务,存储过程也不是原子的right@Pacerier没错。我的意思是,如果我们可以使用proc以某种方式模拟事务,例如,如果我们有一些程序可以与事务表一起模拟提交和回滚操作。@DmitryScript是的,但真正的问题是,我们实际上如何使用非事务表原子地做这些事情?