zoukankan      html  css  js  c++  java
  • 第十二章:重做日志和归档




    [大纲]

    重做日志文件、

    归档日志文件的结构

    重做日志文件、

    归档日志文件工作过程

      管理重做日志文件、

    归档日志


    一、在线重做日志文件


    1.重做日志概述

           在数据库的使用过程中,可能会出现断电、死机等意外情况,在出现意外时如何保证数据的有效性、一致性和完整性?Oracle 作为大型关系数据库管理系统,必须要通过合理的机制确保在任何情况下都不会出现数据丢失,通过合理的配置重做日志可以实现并完成这项任务。利用重做日志文件,在数据库发生故障时,可以重新处理亊务。每个亊务在处理的同时也会写入重做日志缓冲区,然后由 LGWR 进程写入到重做日志文件,这样,如果发生介质故障,重做日志文件将提供恢复机制(但也存在例外情况,例如,在启用NOLOGGING 子句的情况下对象中的直接加载插入。)重做日志文件用来在例程失败等情况下恢复尚未写入数据文件的但是已提交的数据。重做日志文件只用于恢复。

            在 Oracle 当中,亊务对数据库所做的修改将以重做记彔的形式保存重做日志缓存中。在提交亊务时,由 LGWR 进程将缓存中该亊务相关的重做记彔全部写入重做日志文件,这时,亊务认为已经成功提交。这种机制称为“快速提交。

    总结几点:

       1. 数据库维护在线重做日志文件以防止数据丢失。

       2.服务器进程将每个亊务同步写入重做日志缓冲区,然后 LGWR 进程将其写入在线重做日志。

       3. Oracle 数据库仅使用在线重做日志进行恢复。






    2 在线重做日志结构


    重重做日志文件具有以下特征:
         • 记彔对数据所做的所有更改
         • 提供恢复机制
         • 可以划分成组
         • 至少需要两个组
    那么什么是日志组呢(RedoLogGroup)?重做日志组是一组相同的重做日志文件副本,LGWR 后台进程向组内所有联机重做日志文件并发写入相同信息,为保证数据库的正常操作,Oracle 服务器最少需要两个联机 重做日志文件组。属于同一日志组的每个日志文件被称为日志成员,并且同一个日志组的不同日志成员互为镜像,即组内的每个成员都有相同的日志序列号和同样的大小。Oracle 服务器每次写入日志组时,都分配一个日志序列号以唯一地标识每个重做日志文件。当前日志序列号存储在控制文件和所有数据文件的头部。在 Oracle 数据库中,多个重做日志组是循环使用的,如图 6—1 所示。

           假定数据库包含三个日志组,在图 6-1 中,初始阶段后台进程 LGWR 将亊务变化写入日志组一的两个成员中;在日志组一写满之后,LGWR 进程切换到日志组事,并将亊务变化写入到日志组事的两个成员中;在日志组事写满之后,LGWR 进程切换到日志组三,并将亊务变化写入到日志组三;在日志组三写满之后,LGWR 又切换回日志组一,并将亊务变化写入到日志组一,覆盖原有记彔。经过以上说明,大家可以知道,所有亊务变化都可以通过日志组予以保留(归档方式下),样,即使将来出现实例失败(InstanceFailure)或介质失败(Media Failure)时,DBA 将会使用这些已经保留下来的亊务变化进行实例恢复或介质恢复,最终可以确保 Oracle 不会出现数据丢失。

    image




    以下查询显示了当前数据库的重做日志文件的位置和名称。当前数据库共有 3 个日志文件 REDO01.LOG、REDO02.LOG 和 REDO03.LOG


    SQL> select member from v$logfile;
    MEMBER
    --------------------------------------------------------------------------------
    /u01/app/oracle/oradata/orcl/redo02.log
    /u01/app/oracle/oradata/orcl/redo01.log
    /u01/app/oracle/oradata/orcl/redo03.log


    SQL> col member for a40;
    SQL> select member from v$logfile;
    
    MEMBER
    ----------------------------------------
    /u01/app/oracle/oradata/orcl/redo03.log
    /u01/app/oracle/oradata/orcl/redo02.log
    /u01/app/oracle/oradata/orcl/redo01.log
    
    SQL>
    View Code
    SQL> set linesize 100;
    SQL> desc v$logfile;
     Name                                                  Null?    Type
     ----------------------------------------------------- -------- ------------------------------------
     GROUP#                                                         NUMBER
     STATUS                                                         VARCHAR2(7)
     TYPE                                                           VARCHAR2(7)
     MEMBER                                                         VARCHAR2(513)
     IS_RECOVERY_DEST_FILE                                          VARCHAR2(3)
     CON_ID                                                         NUMBER
    
    SQL>




    3 日志序列号和日志切换

       什么是日志序列号:

    image

    SQL> archive log list
    Database log mode              No Archive Mode
    Automatic archival             Disabled
    Archive destination            /u01/app/oracle/product/12.1.0/dbhome_1/dbs/arch
    Oldest online log sequence     132
    Current log sequence           134
    SQL>
    
    
    
    View Code


             Oracle 服务器将对数据库所做的所有更改按顺序记彔到重做日志缓冲区中。LGWR 迚程把重做条目从重做日志缓冲区写入联机重做日志组的其中一个组,这个组叫做当前重做日志组。

    LGWR 进程将在以下情况下写入:
         • 当提交亊务处理时(Commit)
         • 当重做日志缓冲区被写满三分之一时
         • 当重做日志缓冲区内的已更改记彔超过 1MB 时
         • 每隔 3 秒
         • 在 DBWn 将数据库缓冲区高速缓存中修改的块写入数据文件之前


          重做日志文件是以循环方式使用的。每个重做日志文件组用一个递增日志序列号来标识,每次重新使用日志时就会覆盖原来的序列号。LGWR 按顺序向联机重做日志组写入重做信息。一旦当前联机重做日志组被写满 LGWR 就开始写入下一个组。这称为日志切换(LogSwitch)。当最后一个可用联机重做日志文件已满时,LGWR 将返回第一个联机重做日志文件组并开始重新写入。假定数据库有三个重做日志组,第一个日志组为当前日志组,当前日志序列号为 56,LGWR 进程将亊务变化写入第一个重做日志组中,当第一个日志组写满后,LGWR 进程自动切换到第二个日志组,在进行日志切换时,Oracle 服务器完成如下任:

          • 日志序列号自动加 1,即当前日志序列号变为 57,并且将日志序列号连同 SCN 信息写入到控制文件的日志历史记彔中。

          • 促使 CKPT 进程发出检查点,从而使得后台进程 CKPT 将检查点时刻的 SCN 信息 写入到控制文件和数据文件头部,并促使后台进程 DBWR 将数据高速缓存中的脏缓冲区写入到数据文件中。

          • 当数据库处于 ARCHIVELOG(归档) 模式时,日志切换还会促使 ARCH 进程开始归档。 当日志组写满之后OracleServer 会自动进行日志切换;另外,在一些特定情况 DBA 还可以强制系统进行日志切换,这要求用户必须具有 ALTER SYSTEM 系统权限。例如:如果要初除正在使用的日志组,那么首先强制日志切换;当日志组很大,需要很长时间才能写满时,可以强制执行日志切换,以避免重做日志损坏所带来的损失。强制日志切换的命令如:

    SQL> alter system switch logfile;
    SQL>SELECT GROUP#,SEQUENCE#,MEMBERS,STATUS FROM V$LOG;
    image
    
    

            由实例可见,数据库工作一共有 3 个重做日志组,组号是 1、2 和 3,每个组有一个成员。日志切换前,当前日志组为 1 状态为 CURRENT,对应的最大日志序号为 28 志切换后,最小日志序号的日志组 1 被覆盖,日志序号增一变为 29 并成为新的当前日志组。日志组就是这样被循环的使用。

    • UNUSED:表示从未对联机重做日志文件组进行写入。这是刚添加的联机重做日志文件的状态。
    • CURRENT:表示当前的联机重做日志文件组。这说明该联机重做日志文件组是活动的。
    • ACTIVE:表示联机重做日志文件组是活动的,但是并非当前联机重做日志文件组。数据库的崩溃恢复需要该组。它可用于块恢复。它可能已归档,也可能未归档。
    • CLEARING:表示在执行 ALTER DATABASE CLEAR LOGFILE  命令后正在将该 日志重建为一个空日志。日志清除后,其状态更改为 UNUSED。
    • CLEARING_CURRENT:表示正在清除当前日志文件中的已关闭线程。如果切换 时发生某些故障,如写入新日志标头时发生了输入/输出(I/O) 错误,则日志可能处二此状态。
    • INACTIVE:表示例程恢复不再需要联机重做文件日志组。它可能已归档,也可能未归档。

    实验操作:新增日志组成员


    SQL> desc v$Logfile;
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     GROUP#                                             NUMBER
     STATUS                                             VARCHAR2(7)
     TYPE                                               VARCHAR2(7)
     MEMBER                                             VARCHAR2(513)
     IS_RECOVERY_DEST_FILE                              VARCHAR2(3)
     CON_ID                                             NUMBER
    
    SQL> select member from v$Logfile;
    
    MEMBER
    --------------------------------------------------------------------------------
    /u01/app/oracle/oradata/orcl/redo03.log
    /u01/app/oracle/oradata/orcl/redo02.log
    /u01/app/oracle/oradata/orcl/redo01.log
    
    SQL> select  group# from v$Logfile;
    
        GROUP#
    ----------
             3
             2
             1
    
    SQL> select  group# ,bytes/1024/1024||'M' from v$log;
    
        GROUP# BYTES/1024/1024||'M'
    ---------- -----------------------------------------
             1 50M
             2 50M
             3 50M
    
    SQL> alter database add logfile group 4 ('/u01/app/oracle/oradata/orcl/redo04_1.log','/u01/app/oracle/oradata/orcl/redo04_2.log') size 50m;
    
    Database altered.
    
    SQL> select  member from v$Logfile;
    
    MEMBER
    --------------------------------------------------------------------------------
    /u01/app/oracle/oradata/orcl/redo03.log
    /u01/app/oracle/oradata/orcl/redo02.log
    /u01/app/oracle/oradata/orcl/redo01.log
    /u01/app/oracle/oradata/orcl/redo04_1.log
    /u01/app/oracle/oradata/orcl/redo04_2.log
    
    
    SQL> select  group#,bytes from v$Log;
    
        GROUP#      BYTES
    ---------- ----------
             1   52428800
             2   52428800
             3   52428800
             4   52428800
    
    SQL>

    SQL> select  group#,status from v$log;
    
        GROUP# STATUS
    ---------- ----------------
             1 INACTIVE
             2 INACTIVE
             3 CURRENT
             4 UNUSED
    
    SQL>

    SQL> select  group#,status from v$log;
    
        GROUP# STATUS
    ---------- ----------------
             1 INACTIVE
             2 INACTIVE
             3 CURRENT
             4 UNUSED
    
    SQL>  alter system switch logfile;
    
    System altered.
    
    SQL> select group#,status from v$Log;
    
        GROUP# STATUS
    ---------- ----------------
             1 INACTIVE
             2 INACTIVE
             3 ACTIVE
             4 CURRENT
    
    SQL> alter system switch logfile;
    
    System altered.
    
    SQL> select group#,status from v$Log;
    
        GROUP# STATUS
    ---------- ----------------
             1 CURRENT
             2 INACTIVE
             3 ACTIVE
             4 ACTIVE
    
    SQL>



    实验操作:添加日志组成员

    SQL> set linesize 1000;
    SQL> col member for a60;
    SQL> select  group# ,member from v$Logfile;
    
        GROUP# MEMBER
    ---------- ------------------------------------------------------------
             3 /u01/app/oracle/oradata/orcl/redo03.log
             2 /u01/app/oracle/oradata/orcl/redo02.log
             1 /u01/app/oracle/oradata/orcl/redo01.log
             4 /u01/app/oracle/oradata/orcl/redo04_1.log
             4 /u01/app/oracle/oradata/orcl/redo04_2.log
    
    
    SQL> alter database add logfile member '/u01/app/oracle/oradata/orcl/redo02_1.log' to group 2;
    
    Database altered.
    
    SQL> select group#,member from v$logfile;
    
        GROUP# MEMBER
    ---------- ------------------------------------------------------------
             3 /u01/app/oracle/oradata/orcl/redo03.log
             2 /u01/app/oracle/oradata/orcl/redo02.log
             1 /u01/app/oracle/oradata/orcl/redo01.log
             4 /u01/app/oracle/oradata/orcl/redo04_1.log
             4 /u01/app/oracle/oradata/orcl/redo04_2.log
             2 /u01/app/oracle/oradata/orcl/redo02_1.log
    
    6 rows selected.
    
    SQL>



    二:检查点

            在介绍检查点之前,首先回顾一下实例恢复。假定当前日志序列号为 56,先前检查点时的 SCN 值为3456231,并且该 SCN 值被记载到了控制文件和数据文件头部,某用户执行了亊务变化操作,并提交了亊务,SCN 值变化为 3456239,并且此时突然出现了系统断电,那么首先应考虑控制文件、数据文件和重做日志的SCN 值分别为多少。因为只有在发出检查点才会将 SCN 信息写入到控制文件和数据文件头部,所以控制文件和数据文件的 SCN 值都是 3456231,而当执行了提交操作后,重做记彔连同 SCN 会写入到重做日志文件,所以此时重做日志文件的当前 SCN 值为 3456239。因为数据文件、控制文件的 SCN 一致,而与重做日志所记彔的 SCN 不一致,所以在重新启动 Oracle Server 时后台进程 SMON 会进行实例恢复,此时 SMON 程将自动重新执行从 3456231 至 3456239 之间的所有亊务变化,然后才会打开数据库。重做日志为何被称为“RedoLogFile”?因为在进行实例恢复或介质恢复时要重新执行日志文件记彔的所有亊务变化。


    1.生成检查点

      检查点(Checkpoint)是一个数据库亊件,它用于同步所有数据文件、控制文件以及重做日志文件。当后台进程CKPT 发出检查点时,会执行以下两个任务:

    1)后台进程 CKPT 会修改控制文件和数据文件头部,并将当前 SCN 信息写入到这两种文件中,从而使得数据文件、控制文件和重做日志处于一致状态,这就是为何在执行了 SHUTDOWN NORMAL、SHUTDOWN  TRANSACTIONAL 和 SHUTDOWN IMMEDIATE 之后不需要实例恢复(执行这些操作会发出检查点) ,而执行了 SHUTDOWN ABORT(不强制发出检查点)之后需要进行实例恢复的原因。当启动 Oracle 服务器时,后台进程 SMON 总是会检查控制文件、数据文件以及重做日志的一致性:

    •     如果数据文件、控制文件、重做日志的当前 SCN 值完全一致,则系统会直接打开所有数据文件和重做日志。
    •     如果控制文件和数据文件的当前 SCN 值完全一致匹配,并小于重做日志的当前 SCN,则需要进行实例恢复(例如执行 SUHTDOWN ABORT 后)。
    •     如果控制文件和数据文件的当前 SCN 值不匹配,则表示数据文件或控制文件存在损坏,此时就需要进行介质恢复,以恢复损坏的物理文件。

    2)当后台进程 CKPT 工作时,同时会促使后台进程 DBWn 开始工作,并且将数据库高速缓存中的脏缓冲区(DirtyBuffer)写入到数据文件中。检查点可发生在下面情况中:

    •     每次日志切换时 当使用 NORMAL、TRANSACTIONAL、IMMEDIATE  选项关闭例程时
    •     通过设置初始化参数 FAST_START_MTTR_TARGET 强制执行时
    •     数据库管理员通过手动方式请求时 ALTER TABLESPACE [OFF LINE NORMAL| READ ONLY|BEGINBACKUP] 命令导致对特定数据文件执行检查点操作





    2.强制检查点

            假定数据库包含两个日志组,每个日志组尺寸为 100MB,并且初始阶段只有在日志切换时才会发出检查点。假定当前日志组为日志组一,当该日志组写满之后,系统会自动切换到日志组二,并发出检查点将 SCN 信息写入到数据文件和控制文件。如果在日志组二记载了 90MB 亊务变化之后,系统出现断电。可以设想一下,数据库还能使用吗?答案是肯定的,将来在重新启动OracleServer 时后台进程 SMON 会自动执行实例恢复,最终将数据文件、控制文件、重做日志转变为一致状态。当进行实例恢复时,SMON 首先重新执行亊务,然后打开数据库,最后回退未提交的亊务。因为 SMON 需要重新执行日志组事所记载的 90MB 亊务变化,从而会使得实例恢复需要徆长时间。为了降低实例恢复时间,必须要增加检查点次数。日志切换和检查点操作是在数据运行中的某些特定点自执行的,但 DBA 可以强制执行日志切换或检查点操作。强制执行检查点有两种方式:


          1)设置 FAST_START_MTTR_TARGET可以在初始化参数文件中设置此参数,代表实例恢复所用时间,单位为秒。例如:设置FAST_START_MTTR_TARGET=300,代表如果数据库需要实例恢复,那么恢复的时间不超过 300 秒。系统会根据 300 秒时间动计算可以保留的脏块的数目,如果超过则自动发出检查点。

          2)ALTER SYSTEM CHECKPOINT 命令必要时,DBA 也可以手劢发出检查点命令,命令如下:ALTER SYSTEM CHECKPOIN








    3.日志管理策略

        要确定一个数据库例程的联机重做日志文件的合适数量,必须测试不同的配置。在规划重做日志的配置时,需考虑如下几点:

    1)重做日志组的个数

        在某些情况下,数据库例程可能只需要两个组。在其它情况下,数据库例程可能需要更多的组以保证各个组始终可供 LGWR 进程使用。例如,如果跟踪文件或警告文件中出现如下消息:Checkpoint not complete Redo Log Group not archived,表明 LGWR 经常不得不因为检查点操作尚未完成或者日志组尚未归档而等待,这时就需要添加日志组。

    2)重做日志文件的复用

           重做日志对于数据库正常运作和维护都是至关重要,因此建议创建复用重做日志文件来提高重做日志的可靠性。即一个重做日志组中包含多个互为镜像的重做日志成员。复用重做日志文件后,LGWR 进程将同步写入位于一个重做日志组中的多个成员日志文件,即多个日志成员是互为镜像的关系,因此,即使由于某个单独的日志文件破坏或丢失,数据库运行和恢复也不受任何影响。

           尽管 Oracle 服务器允许多元备份的组可以包含不同数量的成员,但应该尽量建立对称配置。不对称配置应只是非常情况(如磁盘故障)的临时结果。在这种情况下,必须先创建新的不同大小的联机重做日志文件组,然后删除旧组.

    3)重做日志文件的位置

            复用联机重做日志文件时,最好将组内的成员放置在不同磁盘上。这样即使一个日志成员所在磁盘发生物理损坏,而其它的日志成员至少还有一个是可用,那么数据库实例不会被中断动行。将归档日志文件和联机重做日志文件分放在不同磁盘上,以减少 ARCnLGWR 后台进程之间的争用。数据文件和联机重做日志文件应当放置在不同的磁盘上以减 少 LGWRDBWn 的争用,并降低发生介质故障时同时丢失数据文件和联机重做日志文件的风险。

    4)重做日志文件的大小

           联机重做日志文件最小为 50KB,最大文件大小视操作系统而定。假定日志组尺寸很小(500KB),那么可能会导致日志切换非常频繁,间接地增加检查点次数,从而降低系统性能;假定日志组尺寸很大(100MB),那么出现意外情况时可能会导致实例恢复的时间很长。Oracle 推荐日志切换时间应该在 20—30min 之间,至于到底应该将日志组尺寸设置为多少,还应该根据实际情况进行反复测试。另外,如果数据库处于ARCHIVELOG(归档) 模式,还应该考虑存放归档日志的存储介质(磁带或磁盘),以使得存储介质剩余空间最小。例如,假定磁带空间为100MB,并且该磁带叧能存放两个归档日志,那么设置重做日志的尺寸略低于 50MB。

        下面的情况可能影响联机重做日志文件的配置:

         • 日志切换和检查点的数量

         • 重做记彔的量和个数

         • 存储介质的空间量;

      例如,启用归档时归档文件所在磁盘上的空间量。



    4.日志操作

            通常,DBA 会在创建数据库时按照计划创建所需重做日志组和各个组成员日志文件。然而在有些情况下,会需要通过手工方式为数据库添加新重做日志组和成员。比如,如果当前某个重做日志组由于某种原因无法使用,DBA 需要创建一个新的重做日志组来代替它进行工作。在另外些情况下,DBA 可能会需要改变现有重做日志文件的名称和位置,或者删除重做日志组或成员。在本节中将介绍上述重做日志文件的基本操作。

    1:增加日志组

    --要创建一个新的联机重做日志文件组,请使用下面的 SQL 命令:
    ALTER DATABASE[database] ADD LOGFILE [GROUP integer]  filespec[,[GROUPinteger] filespec]...]
    --可以通过 filespec 来指定成员名称和位置。可以选择每个重做日志文件组的 GROUP 参数值。如果省略了该参数,Oracle 服务器自动生成其值。


    2:删除日志组文件

    ALTER DATABASE[database] DROP LOGFILE MEMBER 'filename'[, 'filename'].


    3:;日志组文件重定位


    使用 ALTER DATABASE RENAME FILE
    
    命令的步骤如下:
    1)关闭数据
    2)使用操作系统命令 COPY 重做日志文件到新位置
    3)启动数据库到 mount 状态
    4)执行 ALTER DATABASERENAME FILE 命令
    5)打开数据库






    三、归档文件

      Oracle 数据库可运行在两种模式下:ARCHIVELOG 模式和 NO ARCHIVELOG 模式。

    • NO ARCHIVELOG 模式只能用于保护实例失败,而不能用于保护介质失败。为了避免数据库物理文件损坏所引起的数据丢失,数据库可运行在 ARCHIVELOG 模式。后者就是所谓的归档模式。

    image






    1:归档日志的作用

           Oracle 能够将已经写满的重做日志文件在被覆盖之前保存到指定位置上,被保存的重做日志文件的集合称为“归档重做日志”,这个操作过程称为“归档”,根据是否进行归档,数据库可以运行在归档模式(ARCHIVELOG)和非归档模式(NO ARCHIVELOG)下,归档操作可由 ARCH 后台进程自动完成,也可由 DBA 手工完成。在NO ARCHIVELOG 模式下,每次联机重做日志文件已满并发生日志切换时,都要覆盖原来联机重做日志文件。直到对重做日志文件组的检查点操作完成后,LGWR 才覆盖该重做日志文件组。如果数据库配置为在 ARCHIVELOG 模式运行下,那么必须将已满的联机重做日志文件的不活动(INACTIVE)组归档。因为对数据库所做的所有更改都记录在联机重做日志文件内,数据库管理员可以使用数据库物理备份和归档的联机重做日志文件恢复数据库,而不会丢失任何已提交数据。数据库创建时,缺省为NO ARCHIVELOG 模式。使用归档日志有两个好处:

        • 恢复:数据库物理备份连同联机重做日志文件和归档重做日志文件可共同确保恢复所有已提交的事务处理。

       • 备份:可在数据库打开时执行备份。

    --#####查看归档模式
    SQL> archive log list;
    Database log mode No Archive Mode
    Automatic archival Disabled
    Archive destination /u01/app/oracle/product/12.1.0/db_1/dbs/arch
    Oldest online log sequence 30
    Current log sequence 32
    --####关闭数据库
    SQL> shutdown immediate;
    Database closed.
    Database dismounted.
    ORACLE instance shut down.
    SQL> startup mount;
    ORACLE instance started.
    Total System Global Area 1509949440 bytes
    Fixed Size 2924640 bytes
    Variable Size 922750880 bytes
    Database Buffers 570425344 bytes
    Redo Buffers 13848576 bytes
    Database mounted.
    --######开启归档
    SQL> alter database archivelog;
    Database altered.
    --######打卡数据库
    SQL> alter database open;
    Database altered.
    --####关闭归档
    Alter database noarchivelog;







    2:归档日志路径

    设置 LOG_ARCHIVE_DEST_n 初始化参数以指定从 1 个归档位置到 31 个归档位置。例如,输入:

    LOG_ARCHIVE_DEST_1 ='LOCATION = / disk1 / archive'
    ####归档命名格式
    LOG_ARCHIVE_FORMAT = arch_%t_%s_%r.arc













    ====================================================

  • 相关阅读:
    Fixed数据类型
    unity3d游戏物体跟着鼠标方向移动
    unity gl 画线
    Unity3D研究院之游戏对象的访问绘制线与绘制面详解(十七)
    像素填充率,纹理填充率,显存带宽
    GPU渲染管线与shader
    Unity协程(Coroutine)原理深入剖析
    C#基本线程同步
    C#多线程编程
    详解C#中的反射
  • 原文地址:https://www.cnblogs.com/ios9/p/10269680.html
Copyright © 2011-2022 走看看