-- 인덱스 조각화 조회

SELECT

            distinct OBJECT_NAME(S.OBJECT_ID) AS 'TableName'

          , I.NAME AS 'IndexName'

          , ROUND(AVG_FRAGMENTATION_IN_PERCENT, 2) AS 'Fragmentation %'

 FROM SYS.DM_DB_INDEX_PHYSICAL_STATS(DB_ID(),NULL,NULL,NULL,NULL) AS S

 INNER JOIN SYS.INDEXES AS I

 ON S.OBJECT_ID = I.OBJECT_ID AND S.INDEX_ID = I.INDEX_ID

 WHERE S.DATABASE_ID = DB_ID() 

 AND I.NAME IS NOT NULL -- HEAP은 무시

 AND OBJECTPROPERTY(S.OBJECT_ID, 'IsMsShipped') = 0 -- 시스템 개체 무시

 and ROUND(AVG_FRAGMENTATION_IN_PERCENT, 2) > 10

 

-- 조각화 테이블에 대한 인덱스 리빌드 및 통계 업데이트.

set quoted_identifier  OFF

DECLARE @tablename varchar(255)

DECLARE @tablename_header varchar(255)

declare @sql varchar(1000)

DECLARE tnames_cursor CURSOR FOR SELECT

            distinct OBJECT_NAME(S.OBJECT_ID) AS 'TableName'

--          , I.NAME AS 'IndexName'

--          , ROUND(AVG_FRAGMENTATION_IN_PERCENT, 2) AS 'Fragmentation %'

 FROM SYS.DM_DB_INDEX_PHYSICAL_STATS(DB_ID(),NULL,NULL,NULL,NULL) AS S

 INNER JOIN SYS.INDEXES AS I

 ON S.OBJECT_ID = I.OBJECT_ID AND S.INDEX_ID = I.INDEX_ID

 WHERE S.DATABASE_ID = DB_ID() -- 현재 데이터베이스

 AND I.NAME IS NOT NULL -- HEAP은 무시

 AND OBJECTPROPERTY(S.OBJECT_ID, 'IsMsShipped') = 0 -- 시스템 개체 무시

 and ROUND(AVG_FRAGMENTATION_IN_PERCENT, 2) > 10

OPEN tnames_cursor

FETCH NEXT FROM tnames_cursor INTO @tablename

WHILE (@@fetch_status <> -1)



    BEGIN

     IF (@@fetch_status <> -2)





         BEGIN

        SELECT @tablename_header = "Updating Indexes FOR table " + RTRIM(UPPER(@tablename))

        PRINT @tablename_header

  SET @sql = 'ALTER INDEX ALL ON ' + @tablename + ' REBUILD WITH (PAD_INDEX = ON, FILLFACTOR = 90) '

    EXEC (@sql)

  PRINT (@sql)

     END

     FETCH NEXT FROM tnames_cursor INTO @tablename

END

PRINT " "

PRINT " "

SELECT @tablename_header = "************* NO MORE TABLES" +

 " *************"

PRINT @tablename_header

PRINT " "

PRINT "Indexes have been updated FOR ALL tables."

DEALLOCATE tnames_cursor

go

 -- 통계 업데이트

 EXEC sp_updatestats @resample='resample';

GO

set quoted_identifier  ON

 

결과 로그

각 테이블 인덱스 별 업데이트 여부

 

리빌드 후 인덱스 조각화 조회

 

조각화 90이상인 테이블들이 많았으나 리빌드 후 50이하로 떨어졌다.

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect string value: '\xF0\x9F\xA5\xAC&g...' for column `{DB 명}`.`{Table 명}`.`{Column}` at row 1
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3876) ~[mysql-connector-java-5.1.38.jar:5.1.38]
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814) ~[mysql-connector-java-5.1.38.jar:5.1.38]
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478) ~[mysql-connector-java-5.1.38.jar:5.1.38]
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625) ~[mysql-connector-java-5.1.38.jar:5.1.38]
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551) ~[mysql-connector-java-5.1.38.jar:5.1.38]
	at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) ~[mysql-connector-java-5.1.38.jar:5.1.38]

 

 패치 후 갑자기?! 포틀릿 데이터 저장시 DB에서 오류 발생

 

확인결과 '옵션' 값들이 encodeURIComponent() 통해서 들어가는데, string으로 변환되어 DB 컬럼에 저장시 오류 발생

 

 

해당 컬럼의 character set 변경하여 해결.

HeidiSQL 에서 바로 변경

 

아래 쿼리로도 변경가능

alter table {테이블 이름} change column {컬럼 이름} {컬럼 이름} {컬럼 속성} collate 
'utf8mb4_unicode_ci'

(ex. ALTER TABLE test_column CHANGE COLUMN a_column a_column LONGTEXT NULL DEFAULT NULL
COLLATE 'utf8mb4_unicode_ci' )

 

 

'A '서버 데이터베이스의 데이터를 'B' 서버 데이터베이스로 내보내기

1. 'B'서버 데이터베이스의 테이블 삭제
2. 'A'서버 데이터베이스를 'B'서버 데이터 베이스로 내보내기

 

1. 'B'서버 데이터베이스의 테이블 삭제 (테스트로 테이블 삭제, 실제 운영 DB에서는 절대 주의 요함)

exec sp_MsForEachTable 'DROP TABLE ?'

 

제약 조건 삭제 Go Go

-- 특정 테이블 제약 조건 확인
SELECT constraint_schema
     , table_name
     , constraint_name
     , column_name
     , ordinal_position
  FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
 WHERE table_name = '(테이블 이름)';

제약 조건 삭제 후 다시  exec sp_MsForEachTable 'DROP TABLE ?' 쿼리 실행해서 테이블 삭제

 

2. 'A'서버 데이터베이스를 'B'서버 데이터 베이스로 내보내기

 

2-1. (데이터베이스 이름) 우클릭 - 태스크(T) - 데이터 내보내기(X)

 

 

2-2. 데이터 원본 선택

- Next - > 데이터 원본 선택 - 데이터 원본(D) : Microsoft OLE DB Driver for SQL Server 선택

- 서버 IP 정보 및 사용자 이름, 비밀번호 입력 후 데이터 베이스 선택

- 연결 테스트 해봄 ( "연결 테스트에 성공했습니다" 팝업 뜨면 OK)

- 확인

 

2-3. 대상 선택

대상(D) :  Microsoft OLE DB Driver for SQL Server 선택- 위 2-2. 데이터 원본 선택과 마찬가지로 IP 정보, 사용자 정보 , 데이터베이스 선택 후 확인

 

2-4. 테이블 복사 또는 쿼리 지정

 

"하나 이상의 테이블 또는 .. " 옵션 선택

2-5. 원본 테이블 및 뷰 선택

복사할 테이블 및 뷰 선택 하고 Next

2-6. 패키지 저장 및 실행

 

2-7. 실행

 

데이터 내보내는 중..

1. 계정 생성

- 보안> 로그인 - 우클릭 - '새 로그인..'

   [페이지 선택 - 일반]

    a. 이름 입력 후 SQL Server 인증(S) 선택 후 암호, 암호 확인 입력

    b. '암호 정책 강제 적용(F)' 체크 해제

   [페이지 선택 - 서버역할]

     a.서버 역할 - public, sysadmin 체크

이후 확인

2. 백업

- 생성한 데이터베이스 우클릭 - 태스트 - 스크립트 생성 

- '개체 선택' 에서 '특정 데이터 베이스 개체 선택( 선택 사항)' 이후 확인

- 스크립팅 옵션 설정 - 스크립트 파일로 저장 - 단일 스크립트 파일(G) 선택 

- '요약' 패스 하고 다음 누르면 아래 이미지처럼 스크립트 저장 완료

 

3. 불러오기

- 파일(F) - 열기(O) - 파일(F)[ctrl +O] 

- 탐색기에서 위 2.백업 에서 저장한 script 파일 선택

- 아래 이미지처럼 스크립트 파일이 열림

- 실행(F5) 

이후 로그창에 에러 뜨는지 확인하면서 대응

ERROR org.springframework.dao.TransientDataAccessResourceException:
### Error updating database. Cause: java.sql.SQLTransientConnectionException: (conn=3359025)
Lock wait timeout exceeded; try restarting transaction
### The error may involve com.goom.app.iam.mapper.UserTimeMapper.modifyLogOnTime-Inline
### The error occurred while setting parameters
### SQL: UPDATE TIM_USER_TIME SET LAST_LOGON = ?, LAST_LOGOUT = ? WHERE TENANT_ID = ? AND USER_ID = ?
### Cause: java.sql.SQLTransientConnectionException:(conn=3359025)
Lock wait timeout exceeded;try restarting transaction ;SQL []; (conn=3359025)
Lock wait timeout exceeded; try restarting transaction; nested exception is java.sql.SQLTransientConnectionException: (conn=3359025)
Lock wait timeout exceeded; try restarting transaction

앱 모바일 https 로그인 관련 테스트 중 갑자기 잘 되던 로그인이 안돼서.. 뭔가 문제 있나? 하고 iPhone으로도 해보고, 스토어에서 바로 다운받은 앱에서도 해봤는데 안돼서 서버 로그를 확인해보니 해당 로그가 오전 11시부터 다수 발견;

 

이 참에 한번 제대로 알아보자.

-- 모든 프로세스 조회
SHOW FULL PROCESSLIST;

Lock 걸린 테이블이 있으면 status 컬럼에 "Waiting for table metadata lock"이라고 표시됨.

 

락걸린 테이블이 없다.. 뭐지?

참고로 해당 프로세스의 id 값을 이용해 프로세스 종료할 수 있다

-- KILL {id}
KILL 3343315;
-- 락 테이블 조회
SELECT * FROM information_schema.INNODB_LOCKS
-- 대기 중인 락 조회
SELECT * FROM information_schema.INNODB_LOCK_WAITS
-- 트랜잭션 조회
SELECT * FROM information_schema.INNODB_TRX

이번 경우는 트랜잭션의 문제 였다 trx_wait_started 가 몇 시간 전으로 찍혀있었다.

 

트랜잭션은 id(trx_id)가 아닌 trx_mysql_thread_id 값을 이용해 kill 시켜줌

-- kill {trx_mysql_thread_id}
KILL 38299;

 

 

참고 사이트:
https://hjjungdev.tistory.com/153
 

Mysql (Maria) Db 테이블락 확인하고 강제중지 방법.

1. 개요 보통 기본설정의 Rdbms는 Select문을 제외하고 Delete/Update/Insert문에 대해서 테이블 락을 걸게됩니다. 가령 A라는 사람이 Delete Table;의 명령문을 실행한 상태에서 커밋을 치지않는 다면 해당커

hjjungdev.tistory.com

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=abc2185&logNo=220756357378

대상 테이블(A)

 

INSERT할 테이블(B)

 

INSERT INTO tpt_favorites(TENANT_ID, USER_UID) (SELECT TENANT_ID, USER_UID FROM tim_user_basiC );

 

정상적으로 가져옴.

 

 

주의사항:
1. 복사하고자 하는 컬럼명이 동일해야하고, 컬럼 명은 순서대로 매칭됨
2. 기본 값이 없을 경우 에러 발생됨
3.  WHERE 절, ORDER BY, GROUP BY 적용 가능

 

[추가] A TABLE 특정 컬럼, B TABLE에 INSERT 하는데 중복 데이터 제외하기 

 

INSERT INTO '테이블A' ('테이블A_컬럼1', '테이블A_컬럼2') 
SELECT '테이블B_컬럼1', '테이블B_컬럼2' FROM '테이블B 
WHERE '(테이블B_중복 제외할 컬럼) NOT IN (SELECT '테이블A_컬럼2' FROM '테이블A')


ex)
INSERT INTO tim_user_addr (TENANT_ID, USER_ID) 
SELECT tenant_id, user_uid FROM tim_user_basic WHERE user_uid NOT IN (SELECT user_id FROM tim_user_addr)
### Cause: java.sql.SQLException: Borrow prepareStatement from pool failed ; uncategorized SQLException for SQL []; SQL state [null]; error code [0]; Borrow prepareStatement from pool failed; nested exception is java.sql.SQLException: Borrow prepareStatement from pool failed default ...

어제 패치 후 오류 발생.. 

 

검색해 보니 'dbcp connection pool에서 connection을 가져오지 못하는 상황'이라는 글을 봄.

 

tomcat 로그를 봤더니..

분명히 추가한 table인데 doesn't exist라니..

 

jdbc.properties 확인 후 어제 table 추가한 db가 아닌 다른 db를 보고 있는 것을 확인하고 다시 추가함.

 

쿼리 수행을 위해 prepareStatement 객체를 생성 도중 에러가 생겨서 DBCP에서 connection을 가져오지 못한 상황

 

참고: https://www.cubrid.com/qna/3800823

https://aljjabaegi.tistory.com/402

MS SQL 컬럼 수정 중..

SQL 오류 (4922): 개체 'XXXXX '은(는) 열 'OOOO'에 종속되어 있습니다.
하나 이상의 개체가 이 열에 액세스하므로  ... 이(가) 실패했습니다.

오류가 발생.

 

검색 결과 특정 Table의 속성을 변경, 삭제하고자 하는 경우 Column 제약 조건( Constratint)으로 속성 변경이 불가함.

 

 

아래 코드 입력하여 제약 조건 확인

 

EXEC sp_help (테이블 이름); 

ex) EXEC sp_help tpt_menu_type;

(이미 삭제해서 해당 constraint_name는 없다.)

ALTER TABLE (테이블 이름) DROP CONSTRAINT (제약 이름);

ALTER TABLE dbo.tpt_menu_type DROP CONSTRINT DF__tpt_menu___MENU___6E6C36D8;

 

이 후 Table 속성 변경하면 정상적으로 적용됨.

 

[참고] https://slowmonk.tistory.com/76

'SQL > msSQL' 카테고리의 다른 글

Index 리빌드 및 통계 업데이트  (0) 2024.07.19
[Server Management Studio] 데이터 내보내기  (0) 2023.02.21
[SQL SM Studio] 계정 생성 및 백업  (0) 2023.02.17

+ Recent posts