Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.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
MYSQL 5的奇怪行为(数据库隔离)_Mysql_Database_Innodb_Transaction Isolation - Fatal编程技术网

MYSQL 5的奇怪行为(数据库隔离)

MYSQL 5的奇怪行为(数据库隔离),mysql,database,innodb,transaction-isolation,Mysql,Database,Innodb,Transaction Isolation,我打开了两个命令窗口来处理我的数据库MySQL5 下面是我正在使用的表结构。应该注意的是,我已经通过执行set autocommit=0;关闭了自动提交功能: 表结构: CREATE TABLE `ajax`.`zipcodes` ( `ZIPCODE` varchar(5) NOT NULL, `CITY` varchar(50) DEFAULT NULL, `STATE` varchar(2) DEFAULT NULL, PRIMARY KEY (`ZIPCODE`) )

我打开了两个命令窗口来处理我的数据库MySQL5

下面是我正在使用的表结构。应该注意的是,我已经通过执行set autocommit=0;关闭了自动提交功能:

表结构:

CREATE TABLE  `ajax`.`zipcodes` (
  `ZIPCODE` varchar(5) NOT NULL,
  `CITY` varchar(50) DEFAULT NULL,
  `STATE` varchar(2) DEFAULT NULL,
  PRIMARY KEY (`ZIPCODE`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
以下是活动顺序:

步骤1: 在命令窗口1中,我执行了以下命令,您还可以看到输出:

mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
步骤2 在第二个命令窗口中,我在命令下方启动了该命令,它挂起,似乎在等待前一个窗口发出提交命令

mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
步骤3 我转到命令window1,执行commit;您可以看到以下输出:

mysql> commit;
Query OK, 0 rows affected (0.00 sec)
同时,我可以看到之前挂起的第二个窗口也执行了命令并打印了以下输出:

mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
Query OK, 1 row affected (3.63 sec)
Rows matched: 1  Changed: 1  Warnings: 0
步骤4 现在,我在第二个窗口中发出commit,以确保即使在第二个会话中也能正确提交所有更改:

mysql> commit;
Query OK, 0 rows affected (0.00 sec)
步骤5 既然两个窗口都发出了commit命令,我认为一切正常,两个会话也必须同步,所以我转到第一个命令窗口并发出以下命令:

mysql> select * from zipcodes where zipcode=5;
+---------+------+-------+
| ZIPCODE | CITY | STATE |
+---------+------+-------+
| 5       | Wil  | AK    |
+---------+------+-------+
1 row in set (0.00 sec)
我很惊讶,因为我期望城市值为“都柏林”,因为第二个命令窗口的更改(即更新)已在步骤4中提交,但我仍然在城市列中获得Wil


我做错了什么?

这与隔离级别有关。如果将隔离级别提高到可序列化,MySQL中的默认值是可重复读取,则不会得到幻影读取

隔离级别和幻影读取在上进行了说明

如果我像你一样运行这个程序,但是使用更高的隔离级别,我会得到你期望的结果

第1次会议 第2次会议 第1次会议 第2次会议 第1次会议 注意:这并不一定意味着您应该始终使用SERIALIZABLE,这是有权衡的。最值得注意的是,数据库在执行SELECT时将获得一个范围锁,并且您将获得更多基于锁的冲突

更新-显式处理事务 因为我们有autocommit=0;在这些脚本中,我们确实应该显式地处理事务,而不是期望启动事务——尽管在大多数情况下,数据库的行为与您执行启动事务时所期望的一样

但是,在显式启动和结束所有事务(包括仅选择的事务)时运行原始示例,您会得到不同的结果:

第1次会议 第2次会议 第1次会议 第2次会议 第1次会议
表在更新操作期间被锁定?您使用的是什么数据库引擎?@Bobby:都在那里:MySQL和InnoDB@a_horse_with_no_name:哦,对不起,我错过了创建表。在步骤5,如果从窗口2运行相同的select-您得到都柏林还是Wil?可重复读取隔离级别不会影响结果,因为我已经通过启动commit命令在两个窗口中结束了事务。因此,当我在第5步时,没有事务处于活动状态。我上面的评论基于我在网上看到的可重复读取隔离级别:可重复读取隔离级别允许事务获取它返回给应用程序的所有数据行的读取锁,并对它插入、更新或删除的所有数据行写入锁。通过使用可重复读取隔离级别,在同一事务中多次发出的SELECT SQL语句将始终产生相同的结果。@Vicky-我认为当您使用autocommit=0时,MySQL认为同一事务有点奇怪;不显式执行启动事务;在每次交易之前。看看我上面的更新-它使用启动事务;在适当的位置,并在使用just REPEATABLE READYep时获得您期望的结果。。。非常感谢您的详细解释。另外,我发现这个URL对这种行为有一些启示:。MYSQL中的多版本并发控制会导致这种行为。
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE  `ajax`.`zipcodes` (
    ->   `ZIPCODE` varchar(5) NOT NULL,
    ->   `CITY` varchar(50) DEFAULT NULL,
    ->   `STATE` varchar(2) DEFAULT NULL,
    ->   PRIMARY KEY (`ZIPCODE`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.07 sec)

mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)

mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
/* continued from previous (was frozen) */
Query OK, 1 row affected (7.54 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.04 sec)

mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE  `ajax`.`zipcodes` (
    ->   `ZIPCODE` varchar(5) NOT NULL,
    ->   `CITY` varchar(50) DEFAULT NULL,
    ->   `STATE` varchar(2) DEFAULT NULL,
    ->   PRIMARY KEY (`ZIPCODE`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.07 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
/* continued from previous (was frozen) */
Query OK, 1 row affected (8.32 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.04 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.04 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY   | STATE |
+---------+--------+-------+
| 5       | Dublin | AK    |
+---------+--------+-------+
1 row in set (0.00 sec)