2017년 11월 20일 월요일

MYSQL 변경후 크래시 헤결

MySQL 버전 : 5.7.19
사용언어 : C++
환경 : OLEDB를 통하여 디비 접근
문제 : MSSQL -> MYSQL로 변경환후 for문을 통해서 백만건 정도를 돌리면 크래시가 발생함

예시)
    #include <ppl.h>

    size_t proc_count = 1000000;
    proc_count++;
    Concurrency::parallel_for(size_t(0), proc_count, [&](size_t i) {
        i;

        std::wstring Conn(L"Provider=MSDASQL.1; Extended Properties=\"Driver={MySQL ODBC 5.3 Unicode Driver};\"; Server=127.0.0.1; Port=1401; Database=Member; User Id=root; Password=1234");
        CDataSource kDataSource;
        CSession kSession;
        CCommand<CDynamicAccessor> rs;

        HRESULT hr = kDataSource.OpenFromInitializationString(Conn.c_str());
        if (SUCCEEDED(hr))
        {
            hr = kSession.Open(kDataSource);
            if (SUCCEEDED(hr))
            {
                hr = rs.Open(kSession, L"select heroidx from tbl_hero limit 1");
                if (SUCCEEDED(hr))
                {
                    rs.MoveNext();
                    rs.Close();
                    kSession.Close();
                    kDataSource.Close();
                }
                else
                {
                    kSession.Close();
                    kDataSource.Close();
                }
            }
            else
            {
                kDataSource.Close();
            }
        }
    }


atldbcli.h에서 메모리 해제될때 발생했음
우선 Connector/C++로 코드를 작성하니 문제가 없음
그래서 https://dev.mysql.com/downloads/connector/ 있는 최신 파일로 모두 설치해 보았지만 문제가 해결되지 않았음
그러다 다른 컴에 설치했을때 문제가 발생하는 경우도 있고 아닌 경우도 발견함
그래서 ms dll쪽 이슈가 있는게 아닐까 판단해서 아래에서 파일을 다운 받아 설치하니 문제가 해결됨
https://www.microsoft.com/en-us/download/details.aspx?id=53339

Microsoft® ODBC Driver 13.1 for SQL Server


그러나 정확히 해당 문제가 원인이지는 판단을 하기에 근거가 부족한 상태임
이렇게 해결까지 대략 3일정도 소요됨

참고사이트
1. Using Access database from Visual C++
2. OLE DB 프로그래밍

2017년 10월 18일 수요일

MySQL ODBC connection string

사용언어 : C++
컴파일 : Visual Studio 2015
DB : mysql-installer-community-5.7.19.0.msi

회사에서 MS SQL 대신에 MY SQL로 대체해서 사용해야 한다는 통지를 받아서 기존 코어 라이브러리에 MY SQL connection string를 추가하는 작업을 진행

atldbcli.h
OpenFromInitializationString 을 통해서 처리하는 구조라 connection string만 맞추면 금방 될것으로 예상했는데 연결이 되지 않아 애를 먹음


참고사이트)
https://dev.mysql.com/doc/index-connectors.html
https://www.connectionstrings.com/mysql/


기존 코어에 있던 스트링은
Provider=OleMySql.MySqlSource.1; Data Source=127.0.0.1,3306; Initial Catalog=world; User Id=root; Password=1234
결과) GetDataSource 에러값 REGDB_E_CLASSNOTREG Class not registered

검색해 보니 Provider를 MySQLProv로 설정하라고 나와서 해보니 동일하게
REGDB_E_CLASSNOTREG Class not registered 에러가 남

그래서 더 찾아보니
Provider 대신 Driver={MySQL ODBC 5.3 UNICODE Driver}; 를 사용하는 곳이 있어서 수정해봄
결과는 GetDataSource 는 S_OK 하지만 Initialize에서 E_FAIL

여기서 부터 삽질이 시작됨
Driver를 MySQL ODBC 5.3 Driver, MySQL ODBC 5.3 ANSI Driver, MySQL ODBC 5.3 Unicode Driver 3개 다 해보고
User Id를 User로 바꿔보고 UID, PWD 등등 수정해보지만 모두 실패

>> 실패케이스
DRIVER={MySQL ODBC 5.3 Driver}; Data Source=127.0.0.1,3306; Initial Catalog=world; User Id=root; Password=1234; OPTION=3
결과) Initialize 에러값  E_UNEXPECTED Catastrophic failure.

Driver = { MySQL ODBC 5.3 UNICODE Driver }; Data Source=127.0.0.1,3306; Database=world; User=root; Password=1234; OPTION=3
결과) Initialize 에러값 DB_SEC_E_AUTH_FAILED Authentication failed.

Provider=MSDASQL; Driver = { MySQL ODBC 5.3 UNICODE Driver }; Server=127.0.0.1; Port=3306; Database=world; User=root; Password=1234; OPTION=3
결과) Initialize 에러값 E_FAIL

그러다 바탕화면에 텍스트파일을 새로 만들고 확장자를 udl로 바꾸고 실행하니

공급자에 Microsoft OLE DB Provider for ODBC Drivers를 선택하고
연결 문자열에 MySQL ODBC 5.3 Unicode Driver을 넣고 저장시켜보니
Provider=MSDASQL.1; Extended Properties="Driver={MySQL ODBC 5.3 Unicode Driver};";
이런식으로 저장이됨

그래서 스트링을 바꿔서 접속해 보니 정상적으로 접속이 되는것을 확인하게 됨
아싸!

결국 최종 스트링은 아래와 같이 이루어짐
Provider=MSDASQL.1; Extended Properties="Driver={MySQL ODBC 5.3 Unicode Driver};"; Server=127.0.0.1; Port=3306; Initial Catalog=world; User Id=root; Password=1234

참고로 Data Source를 사용하면 실패함 ㅠㅠ
Provider=MSDASQL.1; Extended Properties="Driver={MySQL ODBC 5.3 Unicode Driver};"; Data Source=127.0.0.1,3306; Initial Catalog=world; User Id=gameserver; Password=!QAZwsx
결과) Initialize 에러값 E_FAIL


이상 삽질의 결과 공유 끝.

2017년 6월 27일 화요일

락 관련 속도 비교

1. atomic과 mutex 차이
#include <atomic>
#include <iostream>
#include <ppl.h>
#include <Windows.h>

#pragma comment(lib, "Winmm.lib")

    std::atomic<int> bIsWrite = 0;
    //int b = 1;
    //lock
    auto time = timeGetTime();
    Concurrency::parallel_for(0, 100000, [&](int i) {
        i;
        int a = 0;
        if (bIsWrite.compare_exchange_weak(a, 1))
        {
            std::cout << std::endl;
        }
    });
    std::cout << timeGetTime() - time << std::endl;
    //thread

    std::recursive_mutex m_kMutex;
    bool bRead = false;
    time = timeGetTime();
    Concurrency::parallel_for(0, 100000, [&](int i) {
        i;
        std::lock_guard<std::recursive_mutex>kLock(m_kMutex);
        if (bRead == false)
        {
            bRead = true;
            std::cout << std::endl;
        }
    });
    std::cout << timeGetTime() - time << std::endl;

결과
15
50

2017년 4월 26일 수요일

varbinary 뒤에 0 잘림 현상

이번에 작업하면서 이벤트 정보를 varbinary로 아래와 같이 저장하는데


declare @data varbinary(1024)

update event_binary
   set data = @data
 where id = @id


문제는 @data 값이 0x01020300d209000000  이런식인 경우
막상 저장되는 값은 0x01020300d209
이렇게 되는 것이다.

그래서 한동안 삽질하다가 커뮤니티에 물어보니


SET ANSI_PADDING ON 
https://msdn.microsoft.com/ko-kr/library/ms187403.aspx



답변을 받았다


테이블 생성할때 왜 아래와 같이 했는지 이해가 됐다


SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'tbl_event]'))
BEGIN
CREATE TABLE [dbo].[tbl_event](
[IDX] [int] NOT NULL,
[Custom] [varbinary](15) NULL,
 CONSTRAINT [PK_tbl_event] PRIMARY KEY CLUSTERED 
(
[IDX] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO


IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[dbo].[tbl_event]') AND [name] = N'Data')
BEGIN
ALTER TABLE [dbo].[tbl_event] ADD [Data] [varbinary](1024) NULL
END
GO