第二个sessionmysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from test;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    1 |
|    1 |
|    2 |
+------+
6 rows in set (0.00 sec)mysql> alter table test add column name char(5) default 'a';
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0mysql> select * from test;
+------+------+
| id   | name |
+------+------+
|    1 | a    |
|    2 | a    |
|    3 | a    |
|    1 | a    |
|    1 | a    |
|    2 | a    |
+------+------+
6 rows in set (0.00 sec)第一个session:mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from test;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    1 |
|    1 |
|    2 |
+------+
6 rows in set (0.01 sec)mysql> select * from test;
Empty set (0.00 sec)mysql> show global variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
为什么在第二个session中执行alter语句add column之后,第一个session再select就什么也select不出来了,这个很方便试验,mysql版本5.1

解决方案 »

  1.   

    可重复读是指再读未提交情况下是不能更新数据的
    sqlserver的可重复读是不能更新表结构的,至于你说mysql的这种情况,可能是mysql更新表结构需要重建表吧
      

  2.   

    mysql中的特例: 记住就行了,参照:    REPEATABLE READ 这是InnoDB的默认隔离级别。带唯一搜索条件使用唯一索引的SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE 和DELETE语句只锁定找到的索引记录,而不锁定记录前的间隙。用其它搜索条件,这些操作采用next-key锁定,用next-key锁定或者间隙锁定锁住搜索的索引范围,并且阻止其它用户的新插入。 持续读是默认模式,在其中InnoDBzai在READ COMMITTED和REPEATABLE READ隔离级别处理SELECT语句。持续读不在任何它访问的表上设置锁定,因此,其它用户可自由地在持续读在一个表上执行的同一时间修改这些表。 在持续读中,有一个与之前隔离级别重要的差别:在这个级别,在同一事务内所有持续读读取由第一次读所确定的同一快照。这个惯例意味着如果你在同一事务内发出数个无格式SELECT语句,这些SELECT语句对相互之间也是持续的,请参阅15.2.10.4节,“持续非锁定读”。 注意,持续读不在DROP TABLE和ALTER TABLE上作用。持续读不在DROP TABLE上作用,因为MySQL不能使用已经被移除的表,并且InnoDB 破坏了该表。持续读不在ALTER TABLE上作用,因为它在某事务内执行,该事务创建一个新表,并且从旧表往新表中插入行。现在,当你重新发出持续读之时,它不能在新表中看见任何行,因为它们被插入到一个在持续读读取的快照中不可见的事务里。 
      

  3.   

    2楼精辟,1楼说得也很好。MYSQL里面的ALTER TABLE的步骤是
    1:CREATE TABLE NEWTABLE(含最新的表结构);
    2:INSERT INTO NEWTABLE SELECT * FROM OLDTABLE;
    3: DROP TABLE OLDTABLE;
    4: RENAME TABLE NEWTABLE TO OLDTABLE;在这个过程中,SESSION1里面读取的表已经不存在了,那么也就啥都读不出来了。