mariadb를 python에서 테스트하기 위해서 pyodbc를 이용해서 tpcc 테스트를 진행중입니다. 그런데, mariadb odbc 드라이버에서 메모리 할당 오류가 발생합니다. 먼저 문제를 확인하기 위해서 두 가지 방법을 사용해서 메모리 문제를 확인해본 후 드라이버를 업데이트하게 되었습니다. 이 글에서는 dbms 라이브러리에서 발생하는 메모리 오류 문제를 분석하는 과정을 기록합니다.
Table Of Contents
1. ODBC driver를 사용하는 프로그램에 MALLOC_CHECK_ 확인하기
glibc 라이브러리에서 메모리 오류를 확인하고 처리하는 방법을 제어하는 주요 환경 변수는 MALLOC_CHECK_입니다. 이 환경 변수의 값에 따라 다음과 같은 동작이 수행됩니다.
MALLOC_CHECK_ | 값동작 |
0 | 메모리 관리 함수는 오류를 더욱 허용하며 경고를 주지 않습니다. |
1 | 메모리 관리 함수는 문제가 발견되면 표준 오류에 경고 메시지를 출력합니다. |
2 | 메모리 관리 함수는 문제가 발견되면 abort()를 호출합니다. |
그래서, 아래와 같이 MALLOC_CHECK_=2로 놓고 프로그램을 실행하여 테스트 해 본 결과 특이사항이 발견되지 않습니다.
export MALLOC_CHECK_=2
....
python3 tpcc.py --no-load --client 8 mariadb
File "/home/altibase/py-tpcc/pytpcc/drivers/mariadbdriver.py", line 513, in doPayment
self.cursor.execute(q["updateBCCustomer"], [c_balance, c_ytd_payment, c_payment_cnt, c_data, c_w_id, c_d_id, c_id])
pyodbc.OperationalError: ('HY001', '[HY001] [ma-3.2.1][10.6.16-MariaDB-0ubuntu0.22.04.1]Memory allocation error (0) (SQLPutData)')
Aborting some transaction with some error PAYMENT ('HY001', '[HY001] [ma-3.2.1][10.6.16-MariaDB-0ubuntu0.22.04.1]Memory allocation error (0) (SQLPutData)')
2. valgrind 확인해보기
valgrind는 리눅스에서 메모리 오류와 누수(leak)를 검출하는데 사용되는 오픈소스 도구입니다. 이 툴은 바이너리를 수행할 때 이 툴을 통해서 실행시키면 메모리 누수와 오류등을 확인할 수 있습니다.
저의 경우 python에서 동작하는 mariadb의 odbc 프로그램에서 메모리 누수가 의심되는데, 다음과 같이 python 앞에 valgrind를 넣어주면 메모리 오류를 확인할 수 있습니다.
~/py-tpcc/pytpcc$ valgrind --leak-check=full --show-leak-kinds=all --error-limit=no python3 tpcc.py --no-load --client 8 mariadb
결과는 다음과 같이 나타납니다.
==601017== by 0x24B26C: _PyEval_EvalFrameDefault (in /usr/bin/python3.10)
==601017== by 0x2629FB: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601014== For lists of detected and suppressed errors, rerun with: -s
==601017==
==601014== ERROR SUMMARY: 67 errors from 67 contexts (suppressed: 0 from 0)
==601015== LEAK SUMMARY:
==601015== definitely lost: 352 bytes in 11 blocks
==601015== indirectly lost: 0 bytes in 0 blocks
==601015== possibly lost: 56,493 bytes in 91 blocks
==601015== still reachable: 3,548,257 bytes in 5,018 blocks
==601015== suppressed: 0 bytes in 0 blocks
==601015== Reachable blocks (those to which a pointer was found) are not shown.
==601015== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==601015==
==601015== For lists of detected and suppressed errors, rerun with: -s
==601015== ERROR SUMMARY: 67 errors from 67 contexts (suppressed: 0 from 0)
==601017== 9,608 bytes in 12 blocks are possibly lost in loss record 1,517 of 1,564
==601017== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==601017== by 0x224587: _PyObject_GC_NewVar (in /usr/bin/python3.10)
==601017== by 0x24A2E6: ??? (in /usr/bin/python3.10)
==601017== by 0x2629CD: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601017== by 0x24B26C: _PyEval_EvalFrameDefault (in /usr/bin/python3.10)
==601017== by 0x2629FB: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601017== by 0x24B26C: _PyEval_EvalFrameDefault (in /usr/bin/python3.10)
==601017== by 0x2629FB: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601017== by 0x24B26C: _PyEval_EvalFrameDefault (in /usr/bin/python3.10)
==601017== by 0x2629FB: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601017== by 0x24B26C: _PyEval_EvalFrameDefault (in /usr/bin/python3.10)
==601017== by 0x2629FB: _PyFunction_Vectorcall (in /usr/bin/python3.10)
==601017==
==601017== LEAK SUMMARY:
==601017== definitely lost: 1,081 bytes in 13 blocks
==601017== indirectly lost: 799 bytes in 1 blocks
==601017== possibly lost: 59,253 bytes in 96 blocks
==601017== still reachable: 3,558,337 bytes in 5,023 blocks
==601017== suppressed: 0 bytes in 0 blocks
==601017== Reachable blocks (those to which a pointer was found) are not shown.
==601017== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==601017==
==601017== For lists of detected and suppressed errors, rerun with: -s
==601017== ERROR SUMMARY: 74 errors from 74 contexts (suppressed: 0 from 0)
위에서 LEAK SUMMARY에서 보면 결론적으로 메모리 누수가 있을 수 있다고 나타나고 있기 때문에 드라이버를 업데이트 해보기로 하였습니다.
분석 결론
제가 사용한 mariadb 라이브러리는 아래와 같았습니다.
[ma-3.2.1][10.6.16-MariaDB-0ubuntu0.22.04.1
두 가지 증거를 이용해서 위의 버전에 메모리 누수가 있다고 생각하게 되었는데,
1. 동일한 소스로 mariadb 이외의 다른 db를 실행시에는 에러가 나타나지 않았다.
2. valgrind에서 메모리 leak 이 보고되었다.
때문에 mariadb의 odbc 드라이버를 업데이트해 보기로 하였습니다. mariadb의 odbc 드라이버 업데이트하고 사용하는 법은 다음 포스팅에서 계속하겠습니다.
'IT' 카테고리의 다른 글
우분투 리눅스에 오픈소스 RDBMS인 CUBRID 설치하기 - ubuntu linux open source rdbms install (0) | 2024.03.11 |
---|---|
Ubuntu Linux에서 MariaDB ODBC 드라이버 업데이트 하기 - CentOS, RockyOS, RHEL, Debian (21) | 2024.03.11 |
linux에서 메모리 오류 문제 분석하기 - glibc malloc check, valgrind (0) | 2024.03.05 |
디자인 전공자를 위한 가격을 고려한 프리미엄 노트북 추천 (0) | 2024.03.01 |
영상편집 가능한 사무용 가성비 노트북 추천 (21) | 2024.03.01 |