A consistent read
        means that InnoDB uses multi-versioning to
        present to a query a snapshot of the database at a point in
        time. The query sees the changes made by transactions that
        committed before that point in time, and no changes made by
        later or uncommitted transactions. The exception to this rule is
        that the query sees the changes made by earlier statements
        within the same transaction. This exception causes the following
        anomaly: If you update some rows in a table, a
        SELECT sees the latest version of
        the updated rows, but it might also see older versions of any
        rows. If other sessions simultaneously update the same table,
        the anomaly means that you might see the table in a state that
        never existed in the database.
      
        If the transaction
        isolation level is
        REPEATABLE READ (the default
        level), all consistent reads within the same transaction read
        the snapshot established by the first such read in that
        transaction. You can get a fresher snapshot for your queries by
        committing the current transaction and after that issuing new
        queries.
      
        With READ COMMITTED isolation
        level, each consistent read within a transaction sets and reads
        its own fresh snapshot.
      
        Consistent read is the default mode in which
        InnoDB processes
        SELECT statements in
        READ COMMITTED and
        REPEATABLE READ isolation
        levels. A consistent read does not set any locks on the tables
        it accesses, and therefore other sessions are free to modify
        those tables at the same time a consistent read is being
        performed on the table.
      
        Suppose that you are running in the default
        REPEATABLE READ isolation
        level. When you issue a consistent read (that is, an ordinary
        SELECT statement),
        InnoDB gives your transaction a timepoint
        according to which your query sees the database. If another
        transaction deletes a row and commits after your timepoint was
        assigned, you do not see the row as having been deleted. Inserts
        and updates are treated similarly.
          The snapshot of the database state applies to
          SELECT statements within a
          transaction, not necessarily to
          DML statements. If you insert
          or modify some rows and then commit that transaction, a
          DELETE or
          UPDATE statement issued from
          another concurrent REPEATABLE READ
          transaction could affect those just-committed rows, even
          though the session could not query them. If a transaction does
          update or delete rows committed by a different transaction,
          those changes do become visible to the current transaction.
          For example, you might encounter a situation like the
          following:
        
SELECT COUNT(c1) FROM t1 WHERE c1 = 'xyz';
-- Returns 0: no rows match.
DELETE FROM t1 WHERE c1 = 'xyz';
-- Deletes several rows recently committed by other transaction.
SELECT COUNT(c2) FROM t1 WHERE c2 = 'abc';
-- Returns 0: no rows match.
UPDATE t1 SET c2 = 'cba' WHERE c2 = 'abc';
-- Affects 10 rows: another txn just committed 10 rows with 'abc' values.
SELECT COUNT(c2) FROM t1 WHERE c2 = 'cba';
-- Returns 10: this txn can now see the rows it just updated.
        You can advance your timepoint by committing your transaction
        and then doing another SELECT or
        START TRANSACTION WITH
        CONSISTENT SNAPSHOT.
      
This is called multi-versioned concurrency control.
In the following example, session A sees the row inserted by B only when B has committed the insert and A has committed as well, so that the timepoint is advanced past the commit of B.
             Session A              Session B
           SET autocommit=0;      SET autocommit=0;
time
|          SELECT * FROM t;
|          empty set
|                                 INSERT INTO t VALUES (1, 2);
|
v          SELECT * FROM t;
           empty set
                                  COMMIT;
           SELECT * FROM t;
           empty set
           COMMIT;
           SELECT * FROM t;
           ---------------------
           |    1    |    2    |
           ---------------------
        If you want to see the “freshest” state of the
        database, use either the READ
        COMMITTED isolation level or a
        locking read:
      
SELECT * FROM t FOR SHARE;
        With READ COMMITTED isolation
        level, each consistent read within a transaction sets and reads
        its own fresh snapshot. With FOR SHARE, a
        locking read occurs instead: A SELECT blocks
        until the transaction containing the freshest rows ends (see
        Section 17.7.2.4, “Locking Reads”).
      
Consistent read does not work over certain DDL statements:
Consistent read does not work over
DROP TABLE, because MySQL cannot use a table that has been dropped andInnoDBdestroys the table.Consistent read does not work over
ALTER TABLEoperations that make a temporary copy of the original table and delete the original table when the temporary copy is built. When you reissue a consistent read within a transaction, rows in the new table are not visible because those rows did not exist when the transaction's snapshot was taken. In this case, the transaction returns an error:ER_TABLE_DEF_CHANGED, “Table definition has changed, please retry transaction”.
        The type of read varies for selects in clauses like
        INSERT INTO ...
        SELECT, UPDATE
        ... (SELECT), and
        CREATE TABLE ...
        SELECT that do not specify FOR
        UPDATE or FOR SHARE:
By default,
InnoDBuses stronger locks for those statements and theSELECTpart acts likeREAD COMMITTED, where each consistent read, even within the same transaction, sets and reads its own fresh snapshot.To perform a nonlocking read in such cases, set the isolation level of the transaction to
READ UNCOMMITTEDorREAD COMMITTEDto avoid setting locks on rows read from the selected table.