mysql讀寫分離

                                   Mysql主從複製及讀寫分離

主從複製

什麼是主從複製

主從複製,是用來建立一個和主數據庫完全一樣的數據庫環境,稱爲從數據庫;主數據庫一般是準實時的業務數據庫。

主從複製的作用 

1、做數據的熱備,作爲後備數據庫,主數據庫服務器故障後,可切換到從數據庫繼續工作,避免數據丟失。

2、架構的擴展。業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。

3、讀寫分離,使數據庫能支撐更大的併發。在報表中尤其重要。由於部分報表sql語句非常的慢,導致鎖表,影響前臺服務。如果前臺使用master,報表使用slave,那麼報表sql將不會造成前臺鎖,保證了前臺速度。

主從複製原理 

1.數據庫有個bin-log二進制文件,記錄了所有sql語句。

2.我們的目標就是把主數據庫的bin-log文件的sql語句複製過來。

3.讓其在從數據的relay-log重做日誌文件中再執行一次這些sql語句即可。

4.下面的主從配置就是圍繞這個原理配置

5.具體需要三個線程來操作:

  • 1.binlog輸出線程:每當有從庫連接到主庫的時候,主庫都會創建一個線程然後發送binlog內容到從庫。對於每一個即將發送給從庫的sql事件,binlog輸出線程會將其鎖住。一旦該事件被線程讀取完之後,該鎖會被釋放,即使在該事件完全發送到從庫的時候,該鎖也會被釋放。在從庫裏,當複製開始的時候,從庫就會創建兩個線程進行處理:
  • 2.從庫I/O線程:當START SLAVE語句在從庫開始執行之後,從庫創建一個I/O線程,該線程連接到主庫並請求主庫發送binlog裏面的更新記錄到從庫上。從庫I/O線程讀取主庫的binlog輸出線程發送的更新並拷貝這些更新到本地文件,其中包括relay log文件。
  • 3.從庫的SQL線程:從庫創建一個SQL線程,這個線程讀取從庫I/O線程寫到relay log的更新事件並執行。

可以知道,對於每一個主從複製的連接,都有三個線程。擁有多個從庫的主庫爲每一個連接到主庫的從庫創建一個binlog輸出線程,每一個從庫都有它自己的I/O線程和SQL線程。

從庫通過創建兩個獨立的線程,使得在進行復制時,從庫的讀和寫進行了分離。因此,即使負責執行的線程運行較慢,負責讀取更新語句的線程並不會因此變得緩慢。比如說,如果從庫有一段時間沒運行了,當它在此啓動的時候,儘管它的SQL線程執行比較慢,它的I/O線程可以快速地從主庫裏讀取所有的binlog內容。這樣一來,即使從庫在SQL線程執行完所有讀取到的語句前停止運行了,I/O線程也至少完全讀取了所有的內容,並將其安全地備份在從庫本地的relay log,隨時準備在從庫下一次啓動的時候執行語句。【從庫生成兩個線程,一個I/O線程,一個SQL線程;i/o線程去請求主庫 的binlog,並將得到的binlog日誌寫到relay log(中繼日誌) 文件中;主庫會生成一個 log dump 線程,用來給從庫 i/o線程傳binlog;SQL 線程,會讀取relay log文件中的日誌,並解析成具體操作,來實現主從的操作一致,而最終數據一致;】

可以知道,對於每一個主從複製的連接,都有三個線程。擁有多個從庫的主庫爲每一個連接到主庫的從庫創建一個binlog輸出線程,每一個從庫都有它自己的I/O線程和SQL線程。

主從複製如圖:

原理圖2

步驟一:主庫db的更新事件(update、insert、delete)被寫到binlog

步驟二:從庫發起連接,連接到主庫

步驟三:此時主庫創建一個binlog dump thread線程,把binlog的內容發送到從庫

步驟四:從庫啓動之後,創建一個I/O線程,讀取主庫傳過來的binlog內容並寫入到relay log.

步驟五:還會創建一個SQL線程,從relay log裏面讀取內容,從Exec_Master_Log_Pos位置開始執行讀取到的更新事件,將更新內容寫入到slave的db.

主從複製搭建步驟 :

1.linux安裝mysql,使用yum指令安裝:yum install mysql-server 準備兩臺機器分別安裝mysql數據庫

2.安裝完成啓動mysql服務:service mysqld start

3.指定mysql數據庫密碼:/usr/bin/mysqladmin -u root password 'root'

4.測試:mysql -uroot -proot

5.默認裝完mysql不允許遠程訪問[使用root開啓遠程訪問]步驟如下:

  • select user,host,password from user;

  • 刪除沒有密碼的用戶:delete from user where password=’’;

  • 修改端口:允許所有端口進行訪問:update user set host='%';

  • 提交commit;

  • 刷新mysql權限:flush privileges;

  • navicat連接成功:

6.兩臺搭建成功之後測試兩臺機器能否相互連接:[標識連接成功]

[一臺機器連接另一臺mysql]      mysql -u root -p -h 192.168.87.130 -P 3306

[另一臺機器連接本機的mysql]  mysql -u root -p -h 192.168.87.129 -P 3306

7.開始搭建[開始位置]修改mysql的配置文件:vim /etc/my.cnf [下面是添加配置文件的內容]   

server-id=1 [多臺機器的id名字不能相同]

log-bin=mysql-bin

log-slave-updates

slave-skip-errors=all

8.修改完成重新啓動mysql服務指令:service mysqld restart

9.登陸mysql:mysql -uroot -proot  檢測配置是否生效:SHOW VARIABLES like 'server_id';[結束位置]

10.以上的步驟在另一臺機器[mysql從庫]做相同的配置.[開始位置]--[結束位置]

11.查看主節點[主庫]的狀態信息,文件名稱:show master status;

12.在從機上執行指令stop slave;   將如下配置修改後在從機的mysql客戶端執行

將如下配置修改後在從機的mysql客戶端執行
change master to 
master_host='192.168.64.132',
master_user='root',
master_password='root',
master_log_file='mysql-bin.000001',
master_log_pos=106;

13.在從節點[從庫]開啓複製功能指令:start slave;

14.在從機上查看從節點[從庫]狀態:show slave status\G; 表示搭建成功

15.測試連接兩臺服務器: [搭建成功]

  • 在主庫中創建數據庫ems,刷新從庫出現ems數據庫

  • 在主庫中的表添加數據,從庫刷新會同步主庫的數據

搭建主從複製問題解決方案參考:

https://blog.csdn.net/anljf/article/details/6822980

讀寫分離

使用場景

類似淘寶網這樣的網站,海量數據的存儲和訪問成爲了系統設計的瓶頸問題,日益增長的業務數據,無疑對數據庫造成了相當大的負載,同時對於系統的穩定性和擴展性提出很高的要求。隨着時間和業務的發展,數據庫中的表會越來越多,表中的數據量也會越來越大,相應地,數據操作的開銷也會越來越大;另外,無論怎樣升級硬件資源,單臺服務器的資源(CPU、磁盤、內存、網絡IO、事務數、連接數)總是有限的,最終數據庫所能承載的數據量、數據處理能力都將遭遇瓶頸。分表、分庫和讀寫分離可以有效地減小單臺數據庫的壓力。

讀寫分離架構圖

讀寫分離就是:一主多從,讀寫分離,主動同步,是一種常見的數據庫架構,一般來說:

  • 主庫:提供數據庫寫服務;
  • 從庫:提供數據庫讀服務;
  • 主從之間:通過某種機制同步數據,比如MySOL的binlog

 一個主從同步的集羣通常稱爲一個“分組”,這也是分組這個概念的含義。

爲什麼要讀寫分離

  1. 因爲數據庫的“寫”(寫10000條數據到oracle可能要3分鐘)操作是比較耗時的。
  2. 但是數據庫的“讀”(從oracle讀10000條數據可能只要5秒鐘)。
  3. 所以讀寫分離,解決的是,數據庫的寫入,影響了查詢的效率。

什麼時候要讀寫分離

數據庫不一定要讀寫分離,如果程序使用數據庫較多時,而更新少,查詢多的情況下會考慮使用,利用數據庫 主從同步 。可以減少數據庫壓力,提高性能。當然,數據庫也有其它優化方案。memcache 或是 表折分,或是搜索引擎。都是解決方法。

讀寫分離實現

第一種:

代碼已上傳github : [email protected]:13849141963/mysql-maste-slave.git

1.首先我們需要配置多個數據源,我是用xml進行配置的其他方法大同小異,就是多建立了幾個數據源組件對象。[一主一從]

jdbc.properties

mysql.driverClassName.write = com.mysql.jdbc.Driver
mysql.url.write = jdbc:mysql://192.168.64.132:3306/slave?characterEncoding=utf8
mysql.username.write = root
mysql.password.write = root


mysql.driverClassName.read = com.mysql.jdbc.Driver
mysql.url.read = jdbc:mysql://192.168.64.135:3306/slave?characterEncoding=utf8
mysql.username.read = root
mysql.password.read = root

applicationContext.xml 

<context:property-placeholder location="classpath:jdbc.properties"/>


    <!--創建寫數據源-->
    <bean id="writeDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${mysql.driverClassName.write}"/>
        <property name="url" value="${mysql.url.write}"/>
        <property name="username" value="${mysql.username.write}"/>
        <property name="password" value="${mysql.password.write}"/>
        <!--初始化連接大小-->
        <property name="initialSize" value="0"/>
        <!--連接池的最大使用連接數量-->
        <property name="maxActive" value="20"/>
        <!--連接池的最小空閒-->
        <property name="minIdle" value="0"/>
        <!--獲取連接最大等待時間-->
        <property name="maxWait" value="60000"/>
        <property name="validationQuery"><value>SELECT 1</value></property>
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded連接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true" />

        <!-- 監控數據庫 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />

    </bean>

    <!--創建讀數據源-->
    <bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${mysql.driverClassName.read}"/>
        <property name="url" value="${mysql.url.read}"/>
        <property name="username" value="${mysql.username.read}"/>
        <property name="password" value="${mysql.password.read}"/>
        <!--初始化連接大小-->
        <property name="initialSize" value="0"/>
        <!--連接池的最大使用連接數量-->
        <property name="maxActive" value="20"/>
        <!--連接池的最小空閒-->
        <property name="minIdle" value="0"/>
        <!--獲取連接最大等待時間-->
        <property name="maxWait" value="60000"/>
        <property name="validationQuery"><value>SELECT 1</value></property>
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded連接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true" />
        <!-- 監控數據庫 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />
    </bean>

2.使用AbstractRoutingDataSource 的實現類,進行靈活的切換,可以通過AOP或者手動編程設置當前的DataSource,不用修改我們編寫的對於繼承AbstractRoutingDataSource 的實現類的修改,這樣的編寫方式比較好,至於其中的實現原理,讓我細細到來。我們想看看如何去應用,實現原理慢慢的說!

 private Map<Object, Object> targetDataSources;
 private Object defaultTargetDataSource;
 private Map<Object, DataSource> resolvedDataSources;

targetDataSources中保存了key和數據庫連接的映射關係,defaultTargetDataSource表示默認的鏈接,resolvedDataSources這個數據結構是通過targetDataSources構建而來,存儲的結構也是數據庫標識和數據源的映射關係。

下面需要繼承AbstractRoutingDataSource類,實現我們自己的數據庫選擇邏輯DynamicDataSource 類,先上代碼:

/****
 * 產生動態數據源      AbstractRoutingDataSource是spring提供對數據源進行選擇的類
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    /***
     * 根據返回的key決定使用哪個數據源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {

        return ContextDBHolder.getDataSource();
    }
}

 3.創建ContextDBHolder類去設置數據源,使用ThreadLocal進行對數據源進行綁定。


public class ContextDBHolder {
    //使用ThreadLocal進行綁定數據源key,同一個線程使用同一個數據源key
    private static final ThreadLocal<String> t = new ThreadLocal<String>();

    /****
     * 設置數據源
     * @param key
     */
    public static void setDataSource(String key){
        t.set(key);
    }

    /*****
     * 返回數據源
     */
    public static String getDataSource(){
       return t.get();
    }
    /*****
     * 釋放數據源
     */
    public static void closeDataSource(){
        t.remove();
    }
}

4.創建註解 作用在方法上判斷是讀還是寫操作

/****
 * 自定義註解類型:
 *          @Retention :元註解-->修飾註解的註解
 *               RetentionPolicy:SOURCE 源碼有效 編譯之後不會再.class文件中
 *                               CLASS 編譯有效  編譯之後會留在.class文件中 運行時不生效
 *                               RUNTIME  運行時有效
 *          @Target :作用修飾自定義註解類可以加在什麼位置
 *               ElementType:METHOD 使用在方法上
 *                           TYPE   使用在類上
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Read {
}

5.通過aop切面進行動態選擇數據源

/****
 * 作用:根據目標類中調用的方法往DynamicDataSource中的determineCurrentLookupKey方法動態設置返回值
 * 目標類: save update delete  相關方法使用write
 *        query select        相關方法使用read
 */
@Component("chooseDBAdvice")
public class ChooseDBAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //獲取方法對象
        Method method = invocation.getMethod();
        //判斷當前方上是否存在read註解
        boolean annotationPresent = method.isAnnotationPresent(Read.class);
        if(annotationPresent){
            //設置讀數據源
            ContextDBHolder.setDataSource("read");
            System.out.println("設置讀數據源~~~~~~");
        }else{
            //設置寫數據源
            ContextDBHolder.setDataSource("write");
            System.out.println("設置寫數據源~~~~~~");
        }
        //執行目標方法
        Object proceed = invocation.proceed();
        //釋放數據源
        ContextDBHolder.closeDataSource();
        return proceed;
    }
}
 <context:component-scan base-package="com.zy.cn"/>
    <!--具體實現該接口的 bean-->

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--創建寫數據源-->
    <bean id="writeDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${mysql.driverClassName.write}"/>
        <property name="url" value="${mysql.url.write}"/>
        <property name="username" value="${mysql.username.write}"/>
        <property name="password" value="${mysql.password.write}"/>
        <!--初始化連接大小-->
        <property name="initialSize" value="0"/>
        <!--連接池的最大使用連接數量-->
        <property name="maxActive" value="20"/>
        <!--連接池的最小空閒-->
        <property name="minIdle" value="0"/>
        <!--獲取連接最大等待時間-->
        <property name="maxWait" value="60000"/>
        <property name="validationQuery"><value>SELECT 1</value></property>
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded連接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true" />

        <!-- 監控數據庫 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />

    </bean>
    <!--創建讀數據源-->
    <bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${mysql.driverClassName.read}"/>
        <property name="url" value="${mysql.url.read}"/>
        <property name="username" value="${mysql.username.read}"/>
        <property name="password" value="${mysql.password.read}"/>
        <!--初始化連接大小-->
        <property name="initialSize" value="0"/>
        <!--連接池的最大使用連接數量-->
        <property name="maxActive" value="20"/>
        <!--連接池的最小空閒-->
        <property name="minIdle" value="0"/>
        <!--獲取連接最大等待時間-->
        <property name="maxWait" value="60000"/>
        <property name="validationQuery"><value>SELECT 1</value></property>
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />

        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鐘 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded連接時輸出錯誤日誌 -->
        <property name="logAbandoned" value="true" />
        <!-- 監控數據庫 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />
    </bean>

    <!--管理動態數據源-->
    <bean id="dynamicDataSource" class="com.zy.cn.config.DynamicDataSource">
        <property name="targetDataSources">
            <map>
                <entry key="write" value-ref="writeDataSource"/>
                <entry key="read" value-ref="readDataSource"/>
            </map>
        </property>
        <!--<property name="defaultTargetDataSource" value="writeDataSource"/>-->
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource"/>
        <property name="mapperLocations" value="com/zy/cn/mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.zy.cn.entity"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zy.cn.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" order="2"/>

    <!-- 配置druid監控spring jdbc -->
    <bean id="druid-stat-interceptor"
          class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">
    </bean>
    <bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"
          scope="prototype">
        <property name="patterns">
            <list>
                <value>com.zy.cn.dao</value>
            </list>
        </property>
    </bean>
    <aop:config>
        <aop:advisor advice-ref="druid-stat-interceptor"
                     pointcut-ref="druid-stat-pointcut" order="3"/>
    </aop:config>
    <!--配置數據源切面-->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="pc" expression="execution(* com.zy.cn.service.*.*(..))"></aop:pointcut>
        <aop:advisor advice-ref="chooseDBAdvice" pointcut-ref="pc" order="1"></aop:advisor>
    </aop:config>

6.測試增加,修改,查詢可以看出動態切換數據源,說明讀寫分離搭建成功。

第二種:

Mycat 是一個強大的數據庫中間件,不僅僅可以用作讀寫分離、以及分表分庫、容災備份,而且可以用於多
租戶應用開發、雲平臺基礎設施、讓你的架構具備很強的適應性和靈活性,藉助於即將發佈的 Mycat 智能優化模
塊,系統的數據訪問瓶頸和熱點一目瞭然,根據這些統計分析數據,你可以自動或手工調整後端存儲,將不同的
表映射到不同存儲引擎上,而整個應用的代碼一行也不用改變.

架構圖如下:

搭建步驟 【在這裏我們只做讀寫分離】:和上面兩臺機器一樣

1.linux環境下安裝mycat數據庫中間件 下載地址:http://dl.mycat.io/  加壓:tar -zxvf  Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

2.安裝jdk,版本需在1.7以及以上配置環境變量

3.修改mycat 中的conf文件夾下的server.xml,schema.xml文件 【標籤屬性請參看mycat官方文檔】

server.xml

  mycat登錄的用戶名
 <user name="root">mycat登錄的密碼     
                <property name="password">123456</property>
                  別名[隨便]
                <property name="schemas">TESTDB</property>

                <!-- 表級 DML 權限設置 -->
                <!-- 
                <privileges check="false">
                        <schema name="TESTDB" dml="0110" >
                                <table name="tb01" dml="0000"></table>
                                <table name="tb02" dml="1111"></table>
                        </schema>
                </privileges>
                 -->
        </user>

        <user name="user">
                <property name="password">user</property>
                <property name="schemas">TESTDB</property>
                 該用戶只能進行讀操作
                <property name="readOnly">true</property>
        </user>

schema.xml

<mycat:schema xmlns:mycat="http://io.mycat/">
        對應server.xml中schema標籤的值
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
                <table name="user" dataNode="dn1"/>
        </schema>
         <!-- 定義MyCat的數據節點 db1爲需要操作的數據庫-->
        <dataNode name="dn1" dataHost="localhost" database="db1" />

        <dataHost name="localhost" maxCon="1000" minCon="10" balance="3"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!--配置後臺數據庫的IP地址和端口號,還有賬號密碼 -->
                <!-- master負責寫 -->
                <writeHost host="hostM1" url="192.168.64.137:3306" user="root"
                                   password="root">
                        <!--slave負責讀-->
                        <readHost host="hostS2" url="192.168.64.136:3306" user="root" password="root" />
                </writeHost>
        </dataHost>

</mycat:schema>

4.啓動mycat中間件 bin目錄下啓動

./mycat start

5.查看日誌文件 log目錄下

 tail -f -n 100 wrapper.log

6.連接mycat 用戶名密碼均爲mycat中server.xml中進行配置的

mysql -uroot -p123456 -h192.168.64.138 -P8066 -DTESTDB

 7.測試: 在user表中name字段用主機IP,通過日誌查詢發現只會出現從機上的數據IP端口爲從機的端口,添加也是一樣的,

select * from user;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章