최근에 시작된 프로젝트의 데이터베이스 데이터는 포화에 접근하고 있습니다. 가장 큰 테이블 데이터는 3000W에 가깝고 수백만 개의 데이터가있는 테이블이 여러 개 있습니다. 이 프로젝트는 데이터 읽기 시간이 0.05 초를 초과 할 수 없지만 실제 상황은 요구 사항을 충족하지 않아야합니다. Redis 및 Ehcache Cache 기술을 인덱싱하고 사용하면 더 이상 요구 사항을 충족 할 수 없습니다. 따라서 우리는 읽기 및 쓰기 분리 기술을 사용하기 시작했습니다. 아마도 데이터 볼륨이 향후 1 억 명 이상을 초과하면 분산 데이터베이스의 배포를 고려해야합니다. 그러나 현재 분리 및 쓰기 분리 + 캐시 + 색인 + 테이블 파티션 + SQL 최적화 +로드 밸런싱은 1 억 개의 데이터 볼륨의 쿼리 작업을 충족 할 수 있습니다. Spring을 사용하여 읽기 및 쓰기 분리를 달성하는 단계를 살펴 보겠습니다.
1. 배경
우리의 일반적인 응용 프로그램은 데이터베이스에 대해 "더 읽고 덜 쓰기"하는 것입니다. 즉, 데이터베이스에 대한 데이터가 데이터를 읽는 압력이 비교적 높습니다. 한 가지 아이디어는 데이터베이스 클러스터 솔루션을 사용하는 것입니다.
그중 하나는 메인 도서관으로, 데이터를 작성하는 책임이 있으며, 이는 라이브러리 작성;
다른 것들은 모두 도서관에서 나온 것으로 데이터를 읽는 데 책임이 있습니다.
따라서 우리의 요구 사항은 다음과 같습니다.
1. 읽기 라이브러리와 쓰기 라이브러리의 데이터는 일관성이 있습니다. (이것은 매우 중요한 문제입니다. 비즈니스 논리의 처리는 DAO 또는 Mapper 수준이 아닌 서비스 계층에서 처리되어야합니다)
2. 데이터를 작성할 때는 글쓰기 라이브러리에 작성해야합니다.
3. 데이터를 읽으려면 읽기 라이브러리로 가야합니다.
2. 계획
읽기 및 쓰기의 분리를 해결하기위한 두 가지 솔루션이 있습니다 : Application-Layer 솔루션 및 미들웨어 솔루션.
2.1. 애플리케이션 계층 솔루션 :
이점:
1. 여러 데이터 소스가 쉽게 전환 할 수 있으며 프로그램에 의해 자동으로 완료됩니다.
2. 미들웨어가 필요하지 않습니다.
3. 이론적으로 모든 데이터베이스를 지원합니다.
결점:
1. 프로그래머가 완료하고 운영 및 유지 보수가 관련되지 않습니다.
2. 데이터 소스를 동적으로 증가시킬 수 없습니다.
2.2. 미들웨어 솔루션
장단점 :
이점:
1. 소스 프로그램은 변경없이 읽기 및 쓰기 분리를 달성 할 수 있습니다.
2. 데이터 소스를 동적으로 추가하는 것은 프로그램을 다시 시작할 필요가 없습니다.
결점:
1. 프로그램은 미들웨어에 의존하여 데이터베이스를 전환하기가 어렵습니다.
2. 미들웨어는 대중 교통 에이전트로 사용되며 성능이 감소했습니다.
3. 스프링을 사용하여 응용 프로그램 계층을 기반으로 구현하십시오
3.1. 원칙
서비스를 입력하기 전에 AOP를 사용하여 쓰기 라이브러리 사용 또는 읽기 라이브러리를 사용하든 판단을 내리면 쿼리, 찾기, GET 등 및 기타 쓰기 라이브러리로 시작하는 메소드 이름에 따라 판단 기준을 판단 할 수 있습니다.
3.2. DynamicDatasource
import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource;/*** 동적 데이터 소스를 정의하고 통합 스프링에서 제공하는 AbstractroutingDatasource를 구현합니다. DynamicDataSource는 싱글 톤 및 스레드 정보 보안체이므로 DynamicDataSourceHolder가 완료하는 스레드 안전성을 보장하는 데 사용되므로 DectionEcurrentLookupkey 메소드 * * 만 구현하면됩니다. * * @Author Zhijun * */public class dynamicDatasource는 AbsTractroutingDatasource를 확장합니다. }}
3.3. DynamicDatasourceholder
/** * * 스레드 로컬 기술을 사용하여 현재 스레드에서 데이터 소스의 키를 기록하십시오 * @Author Zhijun * */public class dynamicDatasourceHolder {// 라이브러리 개인 정적 최종 문자열 마스터 = "마스터"에 해당하는 데이터 소스 작성; // 라이브러리에 해당하는 데이터 소스를 읽습니다 프리 개인 정적 최종 문자열 슬레이브 = "슬레이브"; // ThreadLocal을 사용하여 현재 스레드의 데이터 소스를 녹음하여 Private STATIC FINNSLOCAL <Stride> holder = New ThreadLocal <string> (); / ** * 데이터 소스 키 * @param key */ public static void putdatasourcekey (문자열 키) {holder.set (key); } / ** * 데이터 소스 키 * @return * / public static string getDatasourcekey () {return holder.get (); } / *** Markup 쓰기 라이브러리* / public static void Markmaster () {putdatasourcekey (마스터); } / *** Markup 읽기 라이브러리* / public static void markslave () {putdatasourcekey (슬레이브); }} 3.4. DataSourceaspect
import org.apache.commons.lang3.stringutils; import org.aspectj.lang.joinpoint;/** * 데이터 소스의 AOP 섹션을 정의하고 서비스의 공개 이름 */public class section */** * @param section { * @param section */** * @param section */** * @execute */execute를 통해 라이브러리를 읽거나 라이브러리를 작성할 시간인지 판단합니다. void ~ void (joinpoint point) {// 현재 실행 된 메소드 이름 String methodname = point.getSignature (). getName (); if (isslave (methodName)) {// read library dynamicdatasourceholder.markslave (); } else {// Write Library As Library DynamicDatasourceHolder.markmaster (); }} / ** * 읽기 라이브러리 여부를 결정하십시오 * @param methodName * @return * / private boolean isslave (string methodname) {// 메소드 이름은 쿼리, 찾기, get, return stringUtils.startSwithAny ( "query", "find", "get")로 시작합니다. }}3.5. 2 개의 데이터 소스를 구성하십시오
3.5.1. jdbc.properties
jdbc.master.driver = com.mysql.jdbc.driverjdbc.mas aracterencoding = utf8 & autoreconnect = true & alluctiqueries = truejdbc.master.username = rootjdbc.master.password = 123456jd bc.slave01.driver = com.mysql.jdbc.driverjdbc.slave01.url = jdbc : mysql : //127.0.0.1 : 3307/mybatis_1128? useunicode = true & ch aracterencoding = utf8 & autoreconnect = true & alluctiqueries = truejdbc.slave01.username = rootjdbc.slave01.password = 123456
3.5.2. 연결 풀을 정의하십시오
<!-연결 풀-> <bean id = "mas <!-데이터베이스의 사용자 이름-> <property name = "username"value = "$ {jdbc.mas 장치는 분수입니다. 기본값은 240입니다. 취소하려면 0.-> <속성 이름 = "idleconnectionTestPeriod"value = "60" /> <!-연결 풀에서 사용되지 않은 최대 연결 수입니다. 장치는 분수입니다. 기본값은 60입니다. 영원히 생존하려면 0.-> <속성 이름 = "idlemaxage"value = "30" /> <!-파티션 당 최대 연결 수-> <속성 이름 = "maxConnectionsPerPartition"value = "150" /> <!-파티션 당 최소의 최소 연결 숫자 = "maxconnectionspertition" 파티션 당 최소 연결 횟수-> <속성 이름 = "maxConnectionSperTartition"value = "150" /> <!-파티션 당 최소 연결 수-> <속성 이름 = "MinConnectionSpartition"value = "5" /> < /bean> <! < /bean> <!-구성 풀-> <bean id = "davatasource"<! 이름 = "DriverClass"value = "$ {jdbc.sliver01.driver}" /> <!-해당 드라이버의 JDBCURL-> <property name = "jdbcurl"value = "$ {jdbc.slave01.url}" /> <!-database username-> username = "username value = "$ {jdbc.slave01.username}" /> <!-데이터베이스의 비밀번호-> <property name = "property name ="valess "value ="$ {jdbc.slave01.password} " /> <!-데이터베이스 연결 풀에서 유휴 연결 간격 시간을 확인하십시오. 장치는 분수입니다. 기본값은 240입니다. 취소하려면 0.-> <속성 이름 = "idleconnectionTestPeriod"value = "60" /> <!-연결 풀에서 사용되지 않은 링크의 최대 생존 시간. 장치는 분수입니다. 기본값은 60입니다. 영원히 생존하려면 0.-> <속성 이름 = "idlemaxage"value = "30" /> <!-파티션 당 최대 연결 수-> <속성 이름 = "maxConnectionsPerPartition"value = "150" /> <!-분할 당 최소 연결 값 = " /ban value =" /ban. 3.5.3. 데이터 소스를 정의하십시오
<!-데이터 소스를 정의하고 구현 한 데이터 소스를 정의하고-> <bean id = "dataSource"> <!-여러 데이터 소스 설정-> <property name = "targetDatasources"> <map key-type = "java.lang.string"> <! value-Ref = "slave01dataSource"/> </map> </map> </property> <!-기본 데이터 소스를 설정합니다.
3.6. 트랜잭션 관리를 구성하고 데이터 소스 표면을 동적으로 전환하십시오
3.6.1. 거래 관리자 정의
<!-정의 트랜잭션 관리자-> <bean id = "transactionManager"> <속성 이름 = "dataSource"ref = "dataSource" /> < /bean>
3.6.2. 거래 정책을 정의합니다
<!-트랜잭션 정책 정의-> <TX : 조언 ID = "TXADVICE"TRANSACTE-MANAGER = "TRANSACTEMANAGER"> <TX : attributes> <! <!-쿼리 메소드 정의 쿼리 메소드 : 메소드 이름 = "query*"read-only = "true" /> <tx : "method name ="read*""true "" /> <tx ": 메소드 이름 ="true " /> <!-메인 라이브러리는 작업을 수행하고 트랜잭션 전파 동작은 기본 동작으로 정의됩니다-> <TX : 메소드 이름 = "저장*"전파 = "필수" /> <tx : "update*"propagation = "필수" /> <TX : 메소드 이름 = "삭제*"propagation = "resited" />-기본적 Transaction Pecolle- <tx :> </tx : 속성> </tx : 조언>
3.6.3. 패싯을 정의하십시오
<!-AOP 섹션 프로세서 정의-> <bean id = "DataSourCeaspect" /> <aop : config> <!-모든 서비스의 모든 방법을 정의합니다.> <aop : pointcut id = "txpointcut"expression = "execution (*xx.xxx.xxxxx.service. <aop : Advisor Advice-Ref = "txadvice"pointcut-ref = "txpointcut"/> <!-섹션을 사용자 정의 섹션 프로세서에 적용하고 -9999는 섹션이 가장 높은 우선 순위 실행-> <aop : 측면 ref = "dataSourCeaspect"order = "-9999"> <aop : <aop : " /> </aop : 측면> </aop : config>
4. 섹션의 구현 개선 및 거래 정책 규칙 일치 사용
이전 구현에서는 트랜잭션 정책에서 정의를 사용하는 대신 메소드 이름과 일치하며 트랜잭션 관리 정책에서 규칙을 일치시킵니다.
4.1. 개선 된 구성
<!-AOP 섹션 프로세서 정의-> <bean id = "dataSourCeaspect"> <!-트랜잭션 정책을 지정-> <속성 이름 = "txadvice"ref = "txadvice"/<!-슬레이브 메소드의 접두사를 지정합니다. (필수)-> <속성 이름 = "SlavemeThodStart"value = "query, 찾기, 찾기
4.2. 개선 된 구현
import java.lang.reflect.field; import java.util.arraylist; import java.util.list; import java.util.map; import org.apache.commons.lang3.stringutils; import org.aspectj.lang.joinpoint; import org.springframework.transapport.ninterceptor.namectrantorcector org.springframework.transaction.interceptor.transactionattribute; import org.springframework.transaction.interceptor.transactionattributesource; import org.sprameframework.transaction.interceptor.transaction interceptor; import org.springframework.util.matchingutils; org.springframework.util.reflectionutils;/*** 마스터 또는 슬레이브 사용 여부를 제어하는 데이터 소스의 AOP 섹션을 정의합니다. * * 트랜잭션 관리에서 트랜잭션 정책이 구성되는 경우 구성된 트랜잭션 정책에서 재시험 적으로 표시하는 방법은 슬레이브를 사용하는 것이며 다른 하나는 마스터를 사용하는 것입니다. * * 트랜잭션 관리를 구성하는 정책이 없으면 메소드 이름 일치 원칙이 채택되고 슬레이브가 쿼리, 찾기 및 get로 시작하는 것으로 사용되며 기타 메소드는 마스터로 사용됩니다. * * @Author Zhijun * */public class dataSourceaspect {private list <string> slavemeThodPattern = new ArrayList <string> (); private static final string [] defaultslaveMethodStart = new String [] { "Query", "find", "get"}; 개인 문자열 [] SlavemeThodStart; / ** * 거래 관리의 정책 읽기 * * @param txadvice * @throws 예외 */ @suppresswarnings ( "선택 취소") public void settxAdvice (transactioninterceptor txadvice)는 예외를 던졌습니다. } // txadvice transactattributesource transactattributesource에서 정책 구성 정보를 얻습니다. if (! (transactionattributesource instance of namematchTransactionAttributesource)) {return; } // 반사 기술을 사용하여 NAMETHTRANSACTIONATTRIBUTESOURCE 객체에서 NAMEMAP 속성 값을 얻습니다. NAMEMATCHTRANSACTIONATTRIBUTESOURCE MATHTRANSACTIONATTRIBUTESOURCE = (NAMEMATCHTRANSACTIONATTRIBUTESORCE) TransActionAttributesource; Field Namemapfield = ReflectionUtils.findfield (nameThtransactionAttributesource.class, "namemap"); namemapfield.setAccessible (true); //이 필드를 액세스하도록 설정 // namemap <string, transactionAttribute> map = (map <string, transactionAttribute>) namemapfield.get (matchtransactionAttributesource); // transactionAttribute> entry : map.entryset ()) {if (! enther.getValue (). iSReadOnly ()) {// 판단 후에도 ReadOnly 정책은 SlaveMethodPattern에 추가하기 전에 정의됩니다. } slaveMeThodPattern.add (entry.getKey ()); }} / *** 서비스 메소드를 입력하기 전에 실행* @param point face object* / public void 이전 (joinpoint point) {// 현재 실행 된 메소드 이름 string methodname = point.getSignature (). getName (); 부울 isslave = 거짓; if (slavemethodpattern.isempty ()) {// 현재 스프링 컨테이너에 구성된 트랜잭션 정책이 없으며 메소드 이름 일치 메소드 isslave = isslave (methodName); } else {// 정책 규칙을 사용하여 (String MappedName : SlavemeThodPattern) {if (iSMatch (MethodName, MappedName)) {isslave = true; 부서지다; }}}} if (isslave) {// read library dynamicdatasourceholder.markslave (); } else {// Write Library As Library DynamicDatasourceHolder.markmaster (); }} / ** * 읽기 라이브러리 여부를 결정하십시오 * @param methodName * @return * / private boolean isslave (string methodName) {// 메소드 이름은 쿼리로 시작합니다. } /** * WildCard 일치 * * 주어진 메소드 이름이 매핑 된 이름과 일치하는 경우 retud return return. *<p>*기본 구현은 "xxx*", "*xxx"및 "*xxx*"일치 및 직접*평등을 확인합니다. 서브 클래스로 재정의 할 수 있습니다. * * * @param methodName 클래스의 메소드 이름 * @param mappedName 이름이 @return * @return * @see org.springframework.util.patternmatchutils (string, string) */ protected boolean ismatch (String methodName, String MappedName) {returnmatchUt (string mappedName) vpatationmatchUtils. MethodName); } / *** 사용자 지정된 슬레이브의 메소드 이름 접두사* @param slavemeThodStart* / public void setSlaveMethodStart (String [] SlavemEthodStart) {this.slevemethodStart = SlavemEthodStart; } public string [] getSlaveMethodStart () {if (this.slevemethodStart == null) {// 지정되지 않은 경우 기본 return defaultslaveMethodStart를 사용하십시오. } return slavemethodStart; }}5. 한 마스터와 여러 노예의 구현
많은 실용적인 사용 시나리오에서 우리는 "마스터, 다중 슬레이브"아키텍처를 사용하므로 이제이 아키텍처를 지원하며 현재 DynamicDatasource 만 수정하면됩니다.
5.1. 구현
import java.lang.reflect.field; import java.util.arraylist; import java.util.list; import java.util.map; import java.util.concurrent.atomic.atomicinteger; import javax.sql.datasource; import org.slf4j.logger; import; org.slf4j.loggerfactory; import org.springframework.jdbc.datasource.lookup.abstroutingdatasource; import org.springframework.util.reflectionutils;/*** 통합을 통해 제공되는 Datasource를 구현하고 구현해야합니다. DINGIMANCURRENTLOOKUPKEY METHON * * DynamicDatasource는 싱글 톤이자 스레드 정보 보안체이므로 ThreadLocal은 DynamicDatasourceHolder에 의해 완료되는 스레드 안전성을 보장하는 데 사용됩니다. * * @Author Zhijun * */public class dynamicDatasource 확장 AbstractroutingDatasource {private static final logger = loggerfactory.getLogger (DynamicDatasource.class); 개인 정수 슬라브 마운트; // 폴링 수, 처음에는 -1, AtomicInteger는 스레드-안전 비공개 Atomicinteger Counter = 새로운 atomicinteger (-1); // 주요 비공개 목록을 기록합니다 <BlavedAtAsources = New ArrayList <BORVER> (0); @override Protected Object DegeNecurrentLookupkey () {// DynamicDatasourceHolder를 사용하여 스레드 안전을 보장하고 현재 스레드에서 데이터 소스 키를 가져옵니다. if (dynamicDatasourceholder.ismaster ()) {Object Key = DynamicDatasourceHolder.getDatasourcekey (); if (logger.isdebugenabled ()) {logger.debug ( "현재 데이터 소스의 키는 :" + key); } 리턴 키; } 개체 키 = getSlaveKey (); if (logger.isdebugenabled ()) {logger.debug ( "현재 데이터 소스의 키는 :" + key); } 리턴 키; } @suppresswarnings ( "선택 취소") @override public void afterProperTiesset () {super.fterProperTiesset (); // 상위 클래스의 ResolvedDatasources 속성은 얻을 수없는 개인 서브 클래스이므로 필드 필드를 얻으려면 반사를 사용해야합니다. FIELDECTIONSFIELD (ABSTRACTROUTINGDATASOURCE.CLASS, "RESOLVEDDATASOURCES"); field.setAccessible (true); // 접근성 설정 시도 {map <object, dataSource> resolvedDatasources = (map <객체, dataSource>) field.get (this); // 읽기 라이브러리의 데이터 양은 총 데이터 소스 수와 같습니다. for (map.entry <object, dataSource> 항목 : resolvedDatasources.entryset ()) {if (dynamicDatasourceholder.mas } slaveDatAsources.add (Entry.GetKey ()); }} catch (예외 e) {logger.error ( "AfterProperTiesset 오류!", e); }} / ** * 폴링 알고리즘 구현 * * @return * / public object getSlaveKey () {// 결과 위자는 다음과 같습니다. if (counter.get ()> 9999) {// 정수 범위 카운터 (-1)를 초과하지 않도록; // 복원} return slavedatasources.get (index); }}6. MySQL 마스터 슬레이브 복제
6.1. 원칙
MySQL 마스터 (마스터)를 복사하는 원칙 (노예라고 함) :
1. 마스터는 데이터 변경을 바이너리 로그로 기록합니다. 즉, 구성 파일 로그 -BIN으로 지정된 파일 (이 레코드는 이진 로그 이벤트, 바이너리 로그 이벤트라고합니다).
2. 슬레이브 카피 마스터의 이진 로그 벤트 (릴레이 로그) (릴레이 로그)
3. 릴레이 로그의 슬레이브 재 작업 이벤트는 자체를 반영하는 데이터를 변경합니다 (데이터 재생)
6.2. 마하 구성 시점에주의를 기울여야합니다
1. 기본 DB 서버 및 슬레이브 DB 서버 데이터베이스 버전은 동일합니다.
2. 마스터 DB 서버 및 슬레이브 DB 서버의 데이터베이스 데이터는 동일합니다 [여기서는 슬레이브의 마스터 백업을 복원하거나 마스터의 데이터 디렉토리를 해당 슬레이브의 데이터 디렉토리에 직접 복사 할 수 있습니다.]
3. 기본 DB 서버는 이진 로그를 활성화하고 기본 DB 서버와 슬레이브 DB 서버 서버는 고유해야합니다.
6.3. 메인 라이브러리 구성 (Windows와 유사)
일부 친구는 마스터 및 슬레이브 데이터베이스의 IP 주소, 사용자 이름 및 계정 구성이 매우 명확하지 않을 수 있습니다. 다음은 내가 테스트 한 마스터 및 슬레이브 구성입니다. IP는 모두 127.0.0.1입니다. 예제를 마친 후에는 쓸 것입니다.
마스터 슬레이브 IP는 다른 구성의 예입니다. 이 예제를 사용하여 구성 메소드를보다 직관적으로 이해할 수 있습니다.
my.ini [mysqld] (라이브러리에서)에서 수정하십시오.
#enable mas 지정되지 않으면 모든 데이터베이스는 동기화 된 Binlog-Do-DB = MyBatis_1128입니다
(my.ini에 입력 된 명령은 아래에 공간이 있어야합니다. 그렇지 않으면 MySQL은 그것을 인식하지 못할 것입니다).
SQL 문 쿼리 상태 실행 : 마스터 상태 표시
위치 값을 기록해야하며 라이브러리에서 동기화 시작 값을 설정해야합니다.
하나 더 말씀 드리겠습니다. MySQL에서 Show Master 상태를 실행하고 my.ini에서 구성된 컨텐츠가 작동하지 않았다는 것을 알게됩니다. my.ini 파일을 선택하지 않았거나 서비스를 다시 시작하지 않았을 수도 있습니다. 후자에 의해 발생할 가능성이 큽니다.
구성을 적용하려면 MySQL 서비스를 끄고 다시 시작해야합니다.
서비스를 닫는 방법 :
Win Key를 열고 Services.msc를 입력하여 서비스를 호출하십시오.
sqlyog를 다시 시작하고 구성이 적용되었음을 확인하십시오.
6.4. 기본 라이브러리에서 동기식 사용자를 만듭니다
#authorized user slave01은 123456 비밀번호를 사용하여 mysqlgrant 복제 슬레이브에 로그인 *.
6.5. 라이브러리의 구성
my.ini에서 수정 :
#specify serverId, 반복되지 않는 한 라이브러리에서 하나의 구성만이 있고 다른 구성은 SQL 문 서버 ID = 102에서 작동합니다.
다음은 SQL을 실행합니다 (슬레이브의 루트 계정을 사용하여 실행) :
changematertomater_hot = '127.0.0.1', // 호스트의 IP 주소 자료 _uer = 'lave01', // 호스트의 사용자 (호스트에서 방금 만든 계정 QL) Mater_Paword = '123456', Mater_port = 3306, mater_log_file = 'myql3306-bin.000006', // filemate_log_po = 1120; // poition
#Start 슬레이브 동기화 시작 슬레이브; #View 동기화 상태 Show Slave Status;
다음은 두 가지 다른 IP 컴퓨터의 마스터 및 슬레이브 구성 방법입니다.
기본 데이터베이스가있는 운영 체제 : Win7
기본 데이터베이스 버전 : 5.0
기본 데이터베이스의 IP 주소 : 192.168.1.111
데이터베이스가있는 운영 체제에서 : Linux
데이터 버전에서 : 5.0
데이터베이스의 IP 주소 : 192.168.1.112
환경을 소개 한 후 구성 단계에 대해 이야기 해 봅시다.
1. 마스터 데이터베이스가 슬레이브 데이터베이스와 정확히 동일해야합니다.
예를 들어 : 기본 데이터베이스의 A 데이터베이스에는 테이블 B, C 및 D가 있으므로 A와 테이블 B, C 및 D의 데이터베이스에는 금형이 새겨 져야합니다.
2. 기본 데이터베이스에서 동기식 계정을 만듭니다.
코드 사본은 다음과 같습니다.
복제 슬레이브, 파일 on *.
192.168.1.112 : 사용자를 사용하여 실행되는 IP 주소입니다.
MSTEST : 새로 만든 사용자 이름입니다
123456 : 새로 만든 사용자 이름의 비밀번호입니다.
위 명령에 대한 자세한 설명은 Baidu에서 가장 잘 수행됩니다. 너무 많이 쓰면 더 불분명하게됩니다.
3. 기본 데이터베이스의 my.ini를 구성합니다 (창 아래에 있기 때문에 my.ini가 아니기 때문에 my.cnf).
[mysqld] server-id = 1log-bin = log-bin = logbinlog-do-db = mstest // mstest 데이터베이스를 동기화하려면 여러 데이터베이스를 동기화하려면 Binlog-Do-DB = 데이터베이스 이름 Binlog-ignore-db = mysql // 데이터베이스를 무시하십시오.
4. 데이터베이스에서 my.cnf를 구성하십시오.
[mysqld] server-id = 2master-host = 192.168.1.111.111mas 몇 가지 복제 -do-db = 데이터베이스 이름 replice-inignore-db = mysql // 무시할 데이터베이스를 추가하십시오.
5. 성공 여부를 확인하십시오
MySQL을 입력하고 명령을 입력하십시오. 슬레이브 상태 표시/g. 다음 이미지가 표시됩니다. slave_io_running과 slave_sql_running이 모두 yes 인 경우 동기화가 성공적으로 성공할 수 있음을 의미합니다.
6. 동기 데이터 테스트.
기본 데이터베이스를 입력하고 명령을 입력하십시오. 하나 (이름) 값 ( 'Beijing')에 삽입;
그런 다음 데이터베이스에서 입력 명령을 입력하십시오.
현재 데이터베이스에서 데이터를 검색하면 동기화가 성공하고 마스터 및 슬레이브가 구현 될 것입니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.