<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>postgresql | bitneer.dev</title>
	<atom:link href="https://www.bitneer.dev/blog/tag/postgresql/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bitneer.dev</link>
	<description>AI 시대에 취미로 하는 코딩</description>
	<lastBuildDate>Tue, 06 Jan 2026 20:59:26 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://www.bitneer.dev/wp/wp-content/uploads/2023/11/cropped-bitneer_Logo_for_Google_200-32x32.png</url>
	<title>postgresql | bitneer.dev</title>
	<link>https://www.bitneer.dev</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>트랜잭션의 격리 수준</title>
		<link>https://www.bitneer.dev/blog/%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%98-%ea%b2%a9%eb%a6%ac-%ec%88%98%ec%a4%80/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Sun, 28 Jun 2020 03:17:03 +0000</pubDate>
				<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[mariadb]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[transaction]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=664</guid>

					<description><![CDATA[<div data-nosnippet>트랜잭션의 격리 수준을 이해하기 위한 배경 지식으로 트랜잭션, 고립성, 이상현상을 먼저 살펴본다. 트랜잭션의 개요 데이터베이스의 여러 연산을 묶어 놓은 것을 사용자의 관점에서는 하나의 단위로 여겨질 수 있다. 예를 들어, 다른 계좌로 돈을 이체하는 것은 사용자의 관점에서 하나의 작업이지만, 데이터베이스 시스템 내에서는 여러 연산을 결합한 것이다. 이처럼, 하나의 논리적인 작업 단위를 위한 연산들의 모음을 트랜잭션(transaction)이라 한다. 데이터의 무결성(integrity)을 보장하려면, 데이터베이스 시스템은 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%98-%ea%b2%a9%eb%a6%ac-%ec%88%98%ec%a4%80/">트랜잭션의 격리 수준</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  트랜잭션의 격리 수준을 이해하기 위한 배경 지식으로 트랜잭션, 고립성,
  이상현상을 먼저 살펴본다.
</p>
<h5>트랜잭션의 개요</h5>
<p>
  데이터베이스의 여러 연산을 묶어 놓은 것을 사용자의 관점에서는 하나의 단위로
  여겨질 수 있다. 예를 들어, 다른 계좌로 돈을 이체하는 것은 사용자의 관점에서
  하나의 작업이지만, 데이터베이스 시스템 내에서는 여러 연산을 결합한 것이다.
  이처럼, 하나의 논리적인 작업 단위를 위한 연산들의 모음을
  <em>트랜잭션(transaction)</em>이라 한다.
</p>
<p>
  데이터의 무결성(integrity)을 보장하려면, 데이터베이스 시스템은 트랜잭션의
  다음과 같은 특성을 관리해야 한다.
</p>
<ul>
  <li>
    <strong>원자성(atomicity):</strong> 트랜잭션의 모든 연산을 데이터베이스에
    반영하든지, 아니면 전혀 반영하지 않아야 한다.
  </li>
  <li>
    <strong>일관성(consistency):</strong> 고립 상태에 있는 트랜잭션의 실행은
    데이터베이스의 일관성을 유지해야 한다. 고립 상태란 동시에 실행하는 다른
    트랜잭션이 없다는 것을 의미한다.
  </li>
  <li>
    <strong>고립성(isolation):</strong> 여러 개의 트랜잭션을 동시에
    실행하더라도, 각 트랜잭션은 동시에 실행하고 있는 다른 트랜잭션을 인식하지
    못해야 한다.
  </li>
  <li>
    <strong>지속성(durability):</strong> 트랜잭션이 성공적으로 끝나면, 그
    트랜잭션이 데이터베이스 시스템에 수정한 내용은 시스템 장애가 발생하더라도
    영속적이어야 한다.
  </li>
</ul>
<p>위의 특성 중에 격리 수준과 관련한 고립성에 대해 좀 더 알아보자.</p>
<h5>고립성</h5>
<p>
  여러 개의 트랜잭션을 동시에 실행하면 성능이 좋아진다. 그러나 여러 트랜잭션의
  연산이 원하지 않는 방향으로 겹쳐 <em>불일치 상태(inconsistent state)</em>가
  발생할 수 있다. 동시에 실행하는 트랜잭션의 문제를 해결하는 방법은 트랜잭션을
  순차적으로 실행하는 것이다. 트랜잭션의 <em>고립성(isolation)</em>은 여러 개의
  트랜잭션을 동시에 실행하여도, 이 트랜잭션들을 순차적으로 실행한 것과 같은
  상태가 되도록 하는 특성이다.
</p>

<h5>이상현상</h5>
<p>
  <em>이상현상(Phenomena)</em>은 동시 실행하는 여러 트랜잭션이 상호 작용하면서
  나타날 수 있는 문제를 의미한다. 읽기 이상현상으로 dirty read, non-repeatable
  read, phantom read 세 가지가 있다. 쓰기 이상현상으로 lost update가 있다.
  이상현상을 예제로 보이기 위해 간단한 student 테이블을 사용할 것이다.
</p>
<table>
  <colgroup>
    <col />
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th>id</th>
      <th>name</th>
      <th>age</th>
    </tr>
    <tr>
      <td>1</td>
      <td>홍길동</td>
      <td>20</td>
    </tr>
    <tr>
      <td>2</td>
      <td>임꺽정</td>
      <td>25</td>
    </tr>
  </tbody>
</table>
<h6>Dirty Read</h6>
<p>
  dirty read는 한 트랜잭션이 진행 중에, 다른 트랜잭션이
  <strong><em>갱신</em></strong
  >은 하였으나 아직 commit하지 않은 데이터를 읽을 때 발생한다.
</p>
<table>
  <colgroup>
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th>T1</th>
      <th>T2</th>
    </tr>
    <tr>
      <td>SELECT age FROM students WHERE id = 1;</td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td>UPDATE students SET age = 21 where id = 1;</td>
    </tr>
    <tr>
      <td>SELECT age FROM students WHERE id = 1; /* 21을 읽는다 */</td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td>ROLLBACK;</td>
    </tr>
  </tbody>
</table>
<p>
  T2 트랜잭션에서 갱신은 하였으나 아직 커밋하지 않은 나이인 21을 T1 트랜잭션이
  읽는다. T2에서 롤백하면 결국 T1은 이상한 값을 읽어 들인 셈이다.
</p>
<h6>Non-repeatable Read</h6>
<p>
  non-repeatable read는 한 트랜잭션이 읽었던 데이터를 다시 읽을 때 데이터가
  변경되는 것으로, 다시 읽기 전에 다른 트랜잭션이 데이터를
  <strong><em>갱신</em></strong
  >하고 <strong><em>commit</em></strong
  >하기 때문에 발생한다. dirty read와 비슷해 보이지만 다른 트랜잭션에서 commit을
  한다는 차이점이 있다.
</p>
<table>
  <colgroup>
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th>T1</th>
      <th>T2</th>
    </tr>
    <tr>
      <td>SELECT age FROM students WHERE id = 1; /* 20을 읽는다 */</td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td>UPDATE students SET age = 21 where id = 1; COMMIT;</td>
    </tr>
    <tr>
      <td>SELECT age FROM students WHERE id = 1; /* 21을 읽는다 */ COMMIT;</td>
      <td></td>
    </tr>
  </tbody>
</table>
<p>
  T1 트랜잭션 내에서 age가 20과 21 두 개의 값을 갖는다. 의도하지 않은 결과가
  발생할 수 있을 것이다.
</p>
<h6>Phantom Read</h6>
<p>
  phantom read는 우리말로 &#8216;유령 읽기&#8217; 정도로 바꿀 수 있겠다. 유령 읽기는 한
  트랜잭션이 진행 중에, 다른 트랜잭션이 <strong><em>추가</em></strong
  >하거나 <strong><em>삭제</em></strong
  >한 <strong><em>행(row)</em></strong
  >의 데이터를 읽어 발생한다.
</p>
<table>
  <colgroup>
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th>T1</th>
      <th>T2</th>
    </tr>
    <tr>
      <td>SELECT * FROM students WHERE age BETWEEN 10 AND 30;</td>
      <td></td>
    </tr>
    <tr>
      <td></td>
      <td>
        INSERT INTO students(id, name, age) VALUES(3, &#8216;장길산&#8217;, 28); COMMIT;
      </td>
    </tr>
    <tr>
      <td>SELECT * FROM students WHERE age BETWEEN 10 AND 30; COMMIT;</td>
      <td></td>
    </tr>
  </tbody>
</table>
<p>T1 트랜잭션에서 의도하지 않은 &#8216;장길산&#8217; 이름을 가진 3번째 행이 나온다.</p>
<h6>Lost Update(Dirty Write)</h6>
<p>
  Lost Update는 &#8216;갱신 손실&#8217;로 대역할 수 있겠다. 갱신 손실은 한 트랜잭션이
  데이터를 갱신한 후 다른 트랜잭션이 그 갱신한 값을 덮어쓸 때 발생한다. 다음의
  예는 한 고객이 잔고가 1000원 계좌에서 500원을 인출하고 있는데 동업자가 400원을
  동시에 출금하는 예이다.
</p>
<table>
  <colgroup>
    <col />
    <col />
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th colspan="2">Transaction 1</th>
      <th colspan="2">Transaction 2</th>
    </tr>
    <tr>
      <td>read(balance) balance = balance &#8211; 500</td>
      <td colspan="1">1000 500</td>
      <td></td>
      <td colspan="1"></td>
    </tr>
    <tr>
      <td></td>
      <td colspan="1"></td>
      <td>read(balance) balance = balance &#8211; 400</td>
      <td colspan="1">1000 400</td>
    </tr>
    <tr>
      <td>write(balance)</td>
      <td colspan="1">500</td>
      <td></td>
      <td colspan="1"></td>
    </tr>
    <tr>
      <td colspan="1"></td>
      <td colspan="1"></td>
      <td colspan="1">write(balance)</td>
      <td colspan="1">600</td>
    </tr>
  </tbody>
</table>
<p>
  잔고에 100원이 남아야 정상이지만 갱신 손실로 600원이 남았다. 위의 예에서 SQL
  문을 사용하지 않고 수식으로 표현하였다. MariaDB, PostgreSQL에서 확인한 바로는
  한 트랜잭션이 갱신을 한 상태에서 다른 트랜잭션이 동일 데이터에 갱신을 시도하면
  대기를 하여야 한다. 즉, 데이터를 갱신한 트랜잭션이 commit이나 rollback을 하기
  전에는 다른 트랜잭션은 동일 데이터를 갱신할 수 없다. 대부분의 DBMS 제품들은
  모든 격리 수준에서 갱신 시 테이블이나 행(row)에 락(lock)을 걸어 lost update가
  발생하지 않도록 하고 있다.
</p>
<h5>격리 수준(Isolation Level)</h5>
<p>
  동시에 실행하는 트랜잭션들을 순차적인 실행 상태로 만드는 것은 성능에 좋지
  않다. 성능과 일관성을 고려하여 트랜잭션에 격리 수준을 지정할 수 있다. SQL
  표준은 네 종류의 트랜잭션 격리 수준을 정의하고 있다. 다음 항목에서 아래로
  내려갈수록 일관성은 좋아지지만, 성능은 떨어진다.
</p>
<ul>
  <li>
    <strong>read uncommited:</strong> 다른 트랜잭션에서 commit하지 않은 데이터를
    읽을 수 있다. 데이터의 정확도가 중요하지 않으면서 트랜잭션의 수행 시간이 긴
    경우에 지정하여 사용할 수 있다.
  </li>
  <li>
    <strong>read commited:</strong> 다른 트랜잭션에서 commit한 데이터만을
    읽는다.
  </li>
  <li>
    <strong>repeatable read:</strong> read commited와 동일하게 다른 트랜잭션에서
    commit한 데이터만을 읽는다. 추가로 트랜잭션 진행 중에 읽었던 데이터를 다시
    읽을 때, 그 중간에 다른 트랜잭션이 그 데이터를 갱신할 수 없다.
  </li>
  <li>
    <strong>serializable:</strong> 동시 진행하는 트랜잭션들이 순차적으로 실행한
    것과 같은 결과가 나와야 한다. <em>직렬성(serializability)</em>에 더하여 연쇄
    복귀(rollback)도 없어야 한다.
  </li>
</ul>
<p>
  SQL 표준은 <strong>serializable</strong>이 디폴트이다. 이 수준은 트랜잭션 간에
  상호 작용이 전혀 없어야 하는 데 현실과는 맞지 않는다. 일반적인 데이터베이스
  시스템은 <strong>read commited</strong>나 <strong>repeatable read</strong>를
  디폴트로 사용한다. 또한, DBMS 제품마다 표준을 구현하는 방법은 다를 수 있다.
</p>
<p>아래의 표는 각 격리 수준에서 발생할 수 있는 이상현상을 나타낸 것이다.</p>
<table>
  <colgroup>
    <col />
    <col />
    <col />
    <col />
  </colgroup>
  <tbody>
    <tr>
      <th></th>
      <th>Dirty Read</th>
      <th>Non-repeatable Read</th>
      <th>Phantom Read</th>
    </tr>
    <tr>
      <th>Read Uncommitted</th>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
    </tr>
    <tr>
      <th>Read Committed</th>
      <td style="background-color: #deebff">발생하지 않음</td>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
    </tr>
    <tr>
      <th>Repeatable Read</th>
      <td style="background-color: #deebff">발생하지 않음</td>
      <td style="background-color: #deebff">발생하지 않음</td>
      <td style="background-color: #ffebe6">발생할 수 있음</td>
    </tr>
    <tr>
      <th>Serializable</th>
      <td style="background-color: #deebff">발생하지 않음</td>
      <td style="background-color: #deebff">발생하지 않음</td>
      <td style="background-color: #deebff">발생하지 않음</td>
    </tr>
  </tbody>
</table>
<p>
  MySQL의 InnoDB엔진은 repeatable read 격리 수준에서 phantom read가 발생하지
  않는다.
</p>
<p>
  PostgreSQL도 마찬가지로 repeatable read 격리 수준에서 phantom read가 발생하지
  않는다. 또한 트랜잭션을 read uncommitted로 설정은 할 수 있지만, dirty read는
  발생하지 않는다.
</p>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://www.amazon.com/gp/product/0070310866?pf_rd_r=QVPWASZQQQVJ3P915ZHY&amp;pf_rd_p=6fc81c8c-2a38-41c6-a68a-f78c79e7253f" target="_blank" rel="noopener noreferrer">Database System Concepts, 3rd</a
    >
    &#8211; Chapter 13 Transactions
  </li>
  <li>
    <a href="https://en.wikipedia.org/wiki/Isolation_(database_systems)" target="_blank" rel="noopener noreferrer">Isolation (database systems) &#8211; Wikipedia</a
    >
  </li>
  <li>
    <a href="https://postgresql.kr/docs/11/transaction-iso.html" target="_blank" rel="noopener noreferrer">PostgreSQL 11.1 문서 &#8211; 13.2. 트랜잭션 격리</a
    >
  </li>
  <li>
    <a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html" target="_blank" rel="noopener noreferrer">MySQL :: MySQL 8.0 Reference Manual :: 15.7.2.1 Transaction Isolation
      Levels</a
    >
  </li>
  <li>
    <a href="https://mariadb.com/kb/en/mariadb-transactions-and-isolation-levels-for-sql-server-users/#isolation-levels-and-locks" target="_blank" rel="noopener noreferrer">MariaDB Transactions and Isolation Levels for SQL Server Users &#8211; MariaDB
      Knowledge Base</a
    >
  </li>
</ul>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%98-%ea%b2%a9%eb%a6%ac-%ec%88%98%ec%a4%80/">트랜잭션의 격리 수준</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>데비안 9(Stretch)에서 10(Buster)으로 업그레이드 시 주의 사항</title>
		<link>https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88-9stretch%ec%97%90%ec%84%9c-10buster%ec%9c%bc%eb%a1%9c-%ec%97%85%ea%b7%b8%eb%a0%88%ec%9d%b4%eb%93%9c-%ec%8b%9c-%ec%a3%bc%ec%9d%98-%ec%82%ac%ed%95%ad/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Wed, 17 Jun 2020 04:38:57 +0000</pubDate>
				<category><![CDATA[네트워크와 시스템 관리]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[upgrade]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=649</guid>

					<description><![CDATA[<div data-nosnippet>데비안 9에서 데비안 10으로 업그레이드 하면서 내가 부딪쳤던 문제들을 정리해 본다. eth0 네트워크 인터페이스 이름의 미지원 네트워크 인터페이스 이름으로 eth0 등을 사용하고 있다면 데비안 10으로 업그레이드하기 전에 새로운 방식의 이름으로 변경해 주어야 한다. 이에 대한 이해를 위해 네트워크 인터페이스에 이름을 부여하는 방법의 변화 과정을 보자. 원래의 간단한 체계(Original Simple Scheme)는 리눅스 커널이 단순히 eth0, eth1 등으로 이름을 붙인다. 이 체계의 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88-9stretch%ec%97%90%ec%84%9c-10buster%ec%9c%bc%eb%a1%9c-%ec%97%85%ea%b7%b8%eb%a0%88%ec%9d%b4%eb%93%9c-%ec%8b%9c-%ec%a3%bc%ec%9d%98-%ec%82%ac%ed%95%ad/">데비안 9(Stretch)에서 10(Buster)으로 업그레이드 시 주의 사항</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  데비안 9에서 데비안 10으로 업그레이드 하면서 내가 부딪쳤던 문제들을 정리해
  본다.
</p>
<h5>eth0 네트워크 인터페이스 이름의 미지원</h5>
<p>
  네트워크 인터페이스 이름으로 <kbd><strong>eth0</strong></kbd> 등을 사용하고
  있다면 데비안 10으로 업그레이드하기 전에 새로운 방식의 이름으로 변경해 주어야
  한다. 이에 대한 이해를 위해 네트워크 인터페이스에 이름을 부여하는 방법의 변화
  과정을 보자. <em>원래의 간단한 체계(Original Simple Scheme)</em>는 리눅스
  커널이 단순히 eth0, eth1 등으로 이름을 붙인다. 이 체계의 문제는 부팅 후에
  eth0과 eth1의 이름이 서로 바뀔 수 있다는 점이다. 이 문제를 해결하기 위한 여러
  방법이 생겨났는데 그중의 하나가
  <em>영속적인 이름 체계(Persistent Names Scheme)</em>이다. 이 체계는 Mac 주소를
  사용하여 고정된 eth0 등의 이름을 부여한다. 이 체계도 완전하지 않고 특히
  가상머신(virtualization)에서 문제가 있다. 그래서 나온 것이 펌웨어/BIOS에서
  제공하는 정보를 사용하는
  <em>예측가능한 이름 체계(Predictable Name Scheme)</em>이다.
</p>
<p>
  데비안 5(Lenny) 즈음부터 영속적인 이름 체계를 사용해 왔다. 데비안
  9(Stretch)에서 예측가능한 이름 체계가 들어 왔다. 데비안 9를 새로 설치하면
  예측가능한 이름 체계를 사용한다. &#8216;<strong>ip a</strong>&#8216; 명령어를 실행하면
  기존의 eth0 대신 하드웨어에 따라 달라지는 <kbd>eno1, enp0s1, wlp1s0</kbd> 등의
  이름을 볼 수 있을 것이다. 새로 설치하는 것이 아니라 업그레이드로 데비안 9까지
  왔다면 여전히 영속적인 이름 체계를 사용할 것이다.
  <kbd>/etc/udev/rules.d/70-persistent-net.rules</kbd> 파일의 존재로 확인할 수
  있다.
</p>
<p>
  데비안 10(Buster)에서 <em>실제 제작자(upstream)</em>가 영속적인 이름 체계를
  공식적으로 지원하지 않는다.
  <a href="https://wiki.debian.org/NetworkInterfaceNames" target="_blank" rel="noopener noreferrer">NetworkInterfaceNames &#8211; Debian Wiki</a
  >
  페이지에서는 영속적인 이름 체계를 데비안 10까지는 사용할 수 있고 데비안
  11(Bullseye) 무렵에 완전히 없어질 것이라 나온다.
  <a href="https://www.debian.org/releases/buster/releasenotes" target="_blank" rel="noopener noreferrer">데비안 10 &#8212; 릴리스 노트</a
  >
  5장에서는 영속적인 이름 체계가 가능할지도 모르지만, 위험할 수 있어 새로운
  이름으로 변경할 것을 권고하고 있다. 어쨌든 영속적인 이름 체계는 피하는 것이
  나을 것이고 이에 대한 몇 가지 방법이 있다.
</p>
<h6>1. 원래의 간단한 체계 사용하기</h6>
<p>
  네트워크 인터페이스를 하나만 가지고 있고 예측가능한 이름 체계를 싫어한다면
  원래의 간단한 체계를 사용할 수 있는 다양한 방법이 있다. 그러나 이것이 지속
  가능할지는 알 수 없다. 다음에서 커널의 옵션을 설정하는 방법을 설명한다.
</p>
<p>
  1.1. <kbd>/etc/default/grub</kbd> 파일의
  <strong><kbd>GRUB_CMDLINE_LINUX_DEFAULT</kbd></strong
  >의 값으로 <strong><kbd>"net.ifnames=0"</kbd></strong
  >을 추가한다.
</p>
<pre class="language-none">
<code>GRUB_CMDLINE_LINUX_DEFAULT=&quot;quiet net.ifnames=0&quot;</code>
</pre>
<p>1.2. update-grub 명령어를 실행한다.</p>
<pre class="language-none">
<code># update-grub</code>
</pre>
<p>
  데비안 9를 새로 설치했다면 위까지 작업한 후 시스템을 재시작하면 eth0을 사용할
  수 있을 것이다. 그러나 영속적인 이름 체계를 사용하여
  <kbd>/etc/udev/rules.d/70-persistent-net.rules</kbd> 파일을 가지고 있다면
  추가적인 작업이 필요하다.
</p>
<p>
  1.3.
  <kbd>/etc/udev/rules.d/70-persistent-net.rules</kbd> 파일을 삭제하거나 이름을
  바꾼다.
</p>
<pre class="language-none line-numbers" data-line="2">
<code># cd /etc/udev/rules.d
# mv 70-persistent-net.rules 70-persistent-net.rules.old</code>
</pre>
<p>1.4. 다음의 명령어로 initrd를 재생성한다.</p>
<pre class="language-none line-numbers" data-line="1">
<code># update-initramfs -u
...</code>
</pre>
<p>1.5. 시스템을 재시작한다.</p>
<pre class="language-none">
<code># systemctl reboot</code>
</pre>

<h6>2. ssh로 접속하여 예측가능한 이름 체계로 변경하기</h6>
<p>
  ssh로 접속하여 원격 시스템의 네트워크 인터페이스 이름을 바꾸는 것은 신중하게
  해야 한다. 오타 하나 때문에 ssh로 접속할 수 없는 불상사가 발생한다. 내가
  사용하는 시스템이 모니터와 키보드 없이 구석에 자리하고 있는데 작업에서 실수가
  발생한다면 상당히 귀찮을 것이다. 시스템이 모니터와 키보드를 가지고 있어 콘솔로
  직접 접근할 수 있다면 작업은 좀 더 편할 것이다. 다음의 설명 중 @reboot cronjob
  등은 콘솔을 가지고 있다면 생략할 수 있으므로 참작하여 보자.
</p>
<p>
  2.1. 먼저 자신이 현재 사용하고 있는 네트워크 인터페이스 이름을 확인한다.
  여기에는 다양한 방법들이 있다.
</p>
<pre class="language-none">
<code># ip a
# cat /etc/udev/rules.d/70-persistent-net.rules
# echo /sys/class/net/[ew]*</code>
</pre>
<p>
  2.2. 영속적인 이름 체계에서 특별한 경우가 아니라면 eth0을 사용하고 있을
  것이다. 다음의 명령어로 eth0을 사용하고 있는 설정 파일들을 찾는다.
</p>
<pre class="language-none">
<code># grep -r eth0 /etc
...</code>
</pre>
<p>
  위의 결과로 나온 대부분은 주석으로 처리한 것이고 실제 변경이 필요한 파일은
  <strong><kbd>/etc/network/interfaces</kbd></strong
  >일 것이다.
</p>
<p>
  2.3. 다음의 명령어로 예측가능한 이름 체계에서 사용할 네트워크 인터페이스
  이름을 찾는다.
</p>
<pre class="language-none" data-line="1,4">
<code># udevadm test-builtin net_id /sys/class/net/eth0 2&gt; /dev/null
ID_NET_NAME_MAC=enxf46d04d4b9f6
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
ID_NET_NAME_PATH=enp3s0</code>
</pre>
<p>
  라인 4에서 나온 <kbd>enp3s0</kbd>이 내가 앞으로 사용해야 할 이름이다. 여러분이
  가지고 있는 하드웨어에 따라 이름은 달라질 것이다. VirtualBox 가상머신의
  데비안은 enp0s3 이름이 나온다.
</p>
<p>2.4. 다음으로 진행하기 전에 무언가 잘못되었을 때를 위한 대비책을 세우자!</p>
<p>2.4.1. 다음의 스크립트는 아래에서 작업할 내용을 복구하는 스크립트이다.</p>
<pre
  class="language-none line-numbers"
  data-line="3,7,8,10,11"
  data-label="/root/revoke_net.sh"
>
<code>#!/bin/bash

sleep 5m

ip a &gt;&gt; /root/network_interfaces.txt
mv -f /etc/network/interfaces /etc/network/interfaces.fail
cp -a -f /etc/network/interfaces.bak /etc/network/interfaces
cp -a -f /etc/udev/rules.d/70-persistent-net.rules.old /etc/udev/rules.d/70-persistent-net.rules
#cp -a -f /root/99-default.link /etc/systemd/network/99-default.link
update-initramfs -u
systemctl reboot</code>
</pre>
<p>
  이 스크립트를 부팅 시 실행할 수 있게 Crontab에 등록할 것이다. 라인 3은 5분을
  대기하기 위한 것이다. 시스템을 재시작하고 ssh로 접속을 할 수 있는지 확인한다.
  접속에 성공하면 이 스크립트를 실행하는 프로세스를 찾아 죽여야 한다. ssh 접속에
  실패한다면 5분 후 라인 5부터 복구 작업을 시작한다. 라인 5는 &#8216;ip -a&#8217; 명령어로
  네트워크 인터페이스의 이름을 확인하기 위한 것이다. 라인 6은 네트워크 이름
  <kbd>enp3s0</kbd>으로 변경했던 /etc/network/interfaces 파일의 이름을 변경하여
  보관해 둔다. 라인 7에서 기존의 eth0 이름을 가진 /etc/network/interfaces로
  복구한다. 라인 8은 /etc/udev/rules.d/70-persistent-net.rules 파일을 복구한다.
  라인 9는 가상머신에 설치한 데비안을 위한 것이다. 가상머신의 데비안을
  사용한다면 라인 8을 주석 처리하고 라인 9의 주석을 제거한다. 라인 10에서
  initrd를 재생성한다. 라인 11에서 시스템을 재시작한다. 시스템을 재시작하면
  기존의 eth0으로 다시 접속할 수 있을 것이다. 접속하자마자 위의 실행 프로세스를
  찾아 죽여야 한다.
</p>
<p>2.4.2. 다음의 명령으로 위에서 작성한 스크립트에 실행 모드를 추가한다.</p>
<pre class="language-none">
<code># chmod +x /root/revoke_net.sh</code>
</pre>
<p>
  2.4.3. <strong>crontab -e</strong> 명령어를 사용하여 다음의 내용을 추가한 후
  저장한다.
</p>
<pre class="language-none line-numbers" data-line="1,3">
<code># crontab -e
...
@reboot /root/revoke_net.sh</code>
</pre>
<p>
  <strong>crontab -l</strong> 명령어를 실행하여 제대로 등록하였는지 확인해 볼 수
  있다.
</p>
<p>2.5. /etc/network/interfaces 파일을 복구에 사용할 수 있도록 백업해 둔다.</p>
<pre class="language-none">
<code># cp -a /etc/network/interfaces /etc/network/interfaces.bak</code>
</pre>
<p>
  /etc/network/interfaces 파일에서 eth0을 2.3.에서 나온 <kbd>enp3s0</kbd>으로
  변경한다.
</p>
<pre class="language-none line-numbers" data-line="2,3">
<code>...
auto enp3s0
iface enp3s0 inet static
...</code>
</pre>
<p>
  2.6. <kbd>/etc/udev/rules.d/70-persistent-net.rules</kbd> 파일의 이름을
  바꾼다. 가상머신의 데비안이라면 /etc/systemd/network/99-default.link 파일을
  /root 디렉토리로 옮겨준다.
</p>
<pre class="language-none line-numbers" data-line="2">
<code># cd /etc/udev/rules.d
# mv 70-persistent-net.rules 70-persistent-net.rules.old</code>
</pre>
<p>2.7. 다음의 명령어로 initrd를 재생성한다.</p>
<pre class="language-none line-numbers" data-line="1">
<code># update-initramfs -u
...</code>
</pre>
<p>2.8. 시스템을 재시작한다.</p>
<pre class="language-none">
<code># systemctl reboot</code>
</pre>
<p>
  2.9. ssh로 접속해 본다. 접속에 성공한다면 다음과 같이 revoke_net.sh 스크립트를
  실행하는 프로세스를 찾아 죽인다.
</p>
<pre class="language-none line-numbers" data-line="1,3,5">
<code># ps -ef | grep revoke
root       723   717  0 14:58 ?        00:00:00 /bin/sh -c /root/revoke_net.sh
root       724   723  0 14:58 ?        00:00:00 /bin/bash /root/revoke_net.sh
root      1849  1779  0 14:58 pts/0    00:00:00 grep revoke
# kill -9 724
# ps -ef | grep revoke
root      1917  1779  0 14:59 pts/0    00:00:00 grep revoke</code>
</pre>
<p>
  2.10. &#8216;<strong>ip a</strong>&#8216; 명령어로 네트워크 인터페이스의 이름이
  <kbd>enp3s0</kbd>으로 나오는지 확인해 본다.
</p>
<p>
  2.11. 성공적으로 작업을 마쳤으면 정리에 들어간다.
  <strong>crontab -e</strong> 명령어를 사용하여 2.4.3.에서 추가한 &#8216;<kbd
    >@reboot /root/revoke_net.sh</kbd
  >&#8216;를 삭제한 후 저장한다. <strong>crontab -l</strong> 명령어로 확인해 본다.
  <kbd>/etc/network/interfaces.bak</kbd> 파일을 삭제한다.
  <kbd>/etc/udev/rules.d/70-persistent-net.rules.old</kbd> 파일은 따로
  보관하거나 삭제한다.
</p>
<h5>기존의 PostgreSQL 데이터베이스는 reindex 필요</h5>
<p>
  데비안 10은 <kbd>glibc</kbd> 로케일 데이터를 업그레이드하기 때문에
  PostgreSQL의 기존 데이터베이스에 대한 인덱스를 다시 만들어야 한다. 가능하다면
  PostgreSQL의 데이터베이스를 사용하는 응용 프로그램을 업그레이드가 끝날 때까지
  잠시 중단하는 것이 좋을 것이다. 업그레이드를 완료한 즉시 다음의 명령어를
  실행한다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># sudo -u postgres reindexdb --all
...</code>
</pre>

<h5>관련 글</h5>
<ul>
  <li>
    <a href="https://www.bitneer.dev/wp/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%84-%ec%83%88-%eb%b2%84%ec%a0%84%ec%9c%bc%eb%a1%9c-%ec%97%85%ea%b7%b8%eb%a0%88%ec%9d%b4%eb%93%9c%ed%95%98%ea%b8%b0/" target="_blank" rel="noopener noreferrer">데비안을 새 버전으로 업그레이드하기</a
    >
  </li>
</ul>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://wiki.debian.org/NetworkInterfaceNames" target="_blank" rel="noopener noreferrer">NetworkInterfaceNames &#8211; Debian Wiki</a
    >
  </li>
  <li>
    <a href="https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/" target="_blank" rel="noopener noreferrer">Predictable Network Interface Names</a
    >
  </li>
  <li>
    <a href="https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html" target="_blank" rel="noopener noreferrer">systemd.net-naming-scheme — Network device naming schemes</a
    >
  </li>
  <li>
    <a href="https://www.debian.org/releases/buster/releasenotes" target="_blank" rel="noopener noreferrer">데비안 10 &#8212; 릴리스 노트</a
    >
  </li>
</ul><p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88-9stretch%ec%97%90%ec%84%9c-10buster%ec%9c%bc%eb%a1%9c-%ec%97%85%ea%b7%b8%eb%a0%88%ec%9d%b4%eb%93%9c-%ec%8b%9c-%ec%a3%bc%ec%9d%98-%ec%82%ac%ed%95%ad/">데비안 9(Stretch)에서 10(Buster)으로 업그레이드 시 주의 사항</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Confluence 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</title>
		<link>https://www.bitneer.dev/blog/confluence-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-posgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Fri, 29 May 2020 22:50:49 +0000</pubDate>
				<category><![CDATA[네트워크와 시스템 관리]]></category>
		<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[confluence]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[postgresql]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=494</guid>

					<description><![CDATA[<div data-nosnippet>데비안 시스템의 Confluence 서버에서 MySQL을 PostgreSQL로 마이그레이션 한 과정을 보여주려고 한다. 내가 사용하는 데비안 9(stretch)의 PostgreSQL 버전은 9.6이다. Confluence는 버전 6.13.8을 설치하고 있다. 먼저 이 버전의 Confluence에서 지원하는 데이터베이스를 볼 필요가 있다. Supported Platforms &#8211; Confluence 6.13을 보면 PostgreSQL 9.4, 9.5, 9.6을 지원하므로 마이그레이션을 진행할 수 있다. 작업을 진행하기 전에 MySQL의 데이터베이스와 Confluence 홈 디렉토리를 백업한다. 뒤에서 서술할 내용에서 Confluence의 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/confluence-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-posgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Confluence 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  데비안 시스템의 Confluence 서버에서 MySQL을 PostgreSQL로 마이그레이션 한
  과정을 보여주려고 한다. 내가 사용하는 데비안 9(stretch)의 PostgreSQL 버전은
  9.6이다. Confluence는 버전 6.13.8을 설치하고 있다. 먼저 이 버전의
  Confluence에서 지원하는 데이터베이스를 볼 필요가 있다.
  <a href="https://confluence.atlassian.com/conf613/supported-platforms-964961686.html" target="_blank" rel="noopener noreferrer">Supported Platforms &#8211; Confluence 6.13</a
  >을 보면 PostgreSQL 9.4, 9.5, 9.6을 지원하므로 마이그레이션을 진행할 수 있다.
  작업을 진행하기 전에 MySQL의 데이터베이스와 Confluence 홈 디렉토리를 백업한다.
  뒤에서 서술할 내용에서 Confluence의 설치 위치는
  <kbd>/opt/share/confluence</kbd>, 홈 디렉토리는
  <kbd>/var/local/lib/confluence</kbd>이다. 여러분이 이와 다르다면 참작해서 보기
  바란다.
</p>
<h5>단계 1. Confluence에 설치한 Atlassian Marketplace 앱의 정보를 확인하기</h5>
<p>
  단계 4에서 보겠지만 기존 버전과 같은 Confluence를 새로 설치하고 앞으로 그것을
  사용해야 한다. 이전의 Confluence에 있던 앱들은 다시 설치해야 한다. 단계 2에서
  생성하는 XML 포맷의 백업 파일에는 앱의 환경 설정 정보들을 가지고 있다. 이 안의
  동일한 버전으로 앱을 설치해야 문제가 발생하지 않을 것이다. 같은 버전으로 쉽게
  설치하기 위해 앱을 미리 <em>업데이트</em>해 주는 것이 좋을 것이다. 업데이트 후
  앱 이름, 버전, 제작자, 활성화 여부를 기록해 둔다. 나의 경우는 다음과 같다.
</p>
<ul>
  <li>
    Atlassian Troubleshooting and Support Tools / 1.25.0 / Atlassian / enabled
  </li>
  <li>
    Atlassian Universal Plugin Manager Plugin / 3.0.6 / Atlassian / enabled
  </li>
  <li>Confluence Cloud Migration Assistant / 2.6.0 / Atlassian / enabled</li>
  <li>Confluence Mobile Plugin / 2.2.4 / Atlassian / enabled</li>
  <li>Refined for Confluence / 6.1.15 / Refined / enabled</li>
  <li>RefinedMobile for Confluence / 3.3.2 / RefinedWiki / enabled</li>
  <li>Gliffy Diagrams for Confluence / 8.6.5 / Gliffy, Inc. / enabled</li>
  <li>LaTex Math / 3.9.13 / Bolo Software / enabled</li>
</ul>
<h5>단계 2. XML 포맷으로 데이터를 백업하기</h5>
<p>
  이 단계를 진행할 때
  <kbd
    >http://<strong>192.168.1.10:8090</strong>/confluence/admin/backup.action</kbd
  >
  주소처럼 Confluence 서버에 직접 연결한다. IP 주소는 Confluence를 설치한
  시스템의 주소로 여러분에게 맞는 것을 입력한다. Proxy 등과 같이 Confluence
  전단의 Apache로 접속하여 작업하면 에러가 날 가능성이 크다. IP 주소로 직접
  접속할 때 Confluence의 base URL을 변경하라는 메시지가 나오면 무시하고 진행해도
  괜찮다. 다음과 같이 작업한다.
</p>
<ol>
  <li>
    Confluence 설정으로 들어가서
    <strong>ADMINISTRATION &gt; Backup &amp; Restore</strong>를 클릭한다.
  </li>
  <li>
    Export this site에서 디폴트 선택인
    <strong>Include attachments</strong> 체크를 그대로 둔 채
    <strong>Export</strong> 버튼을 클릭한다. 백업할 데이터가 크다면 시간이 오래
    걸린다. 인내심을 가지고 기다린다.
  </li>
  <li>
    작업이 완료되면 새로운 창에서 다음과 같이 백업 성공 메시지와 백업 파일의
    저장 위치가 나온다. 그리고 24시간 안에 이 파일이 지워질 것을 알려준다. 나는
    Proxy Error가 한 번 발생해서
    <strong>xmlexport-20200524-215026-2.zip</strong>처럼 끝에
    <strong>-2</strong>가 붙었다. 이후에 이 파일을 복원에 사용할 것이다.
    <pre class="language-none">
<code>The backup was successfully created at /var/local/lib/confluence/temp/xmlexport-20200524-215026-2.zip. This file will be deleted in 24 hours.</code>
</pre>
  </li>
</ol>
<p>
  attachments가 너무 크다면 <strong>Include attachments</strong>를 체크하지 않는
  것이 좋을 수도 있다. 이 경우 단계 5의 다음 단계에서 이전 Confluence의
  attachments를 새 Confluence로 복사해야 할 것이다. 다음의 명령어 실행으로
  attachments의 크기를 알아볼 수 있다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># du -h /var/local/lib/confluence/attachments
...
4.6G	/var/local/lib/confluence/attachments</code>
</pre>
<p>
  du의 <strong>-h</strong> 옵션은 크기를 읽기 쉽게 K, M, G로 표시해 준다. 나의
  경우 4.6 기가바이트가 나왔는데 attachments 디렉토리를 포함하여 XML 포맷으로
  백업할 수 있었다.
</p>
<h5>단계 3. PostgreSQL의 데이터베이스 만들기</h5>
<p>
  Confluence에서 사용할 PostgreSQL의 데이터베이스를 생성한다. 다음은 psql
  클라이언트를 사용한 진행 과정이다.
</p>
<pre class="language-none" data-line="6,8,10,14">
<code># psql -h localhost -U postgres -d postgres
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=# CREATE ROLE confluence WITH LOGIN PASSWORD &#039;원하는 암호 입력&#039;;
CREATE ROLE
postgres=# CREATE DATABASE confluence WITH ENCODING=&#039;UTF8&#039; OWNER=confluence;
CREATE DATABASE
postgres=# \l
                                  데이터베이스 목록
    이름    |   소유주   | 인코딩 |   Collate   |    Ctype    |      액세스 권한
------------+------------+--------+-------------+-------------+-----------------------
 confluence | confluence | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 jira       | jira       | UTF8   | C           | C           |
 postgres   | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0  | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
            |            |        |             |             | postgres=CTc/postgres
 template1  | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
            |            |        |             |             | postgres=CTc/postgres
(5개 행)</code>
</pre>
<p>
  라인 6에서 <strong>CREATE ROLE</strong>로 <kbd>confluence</kbd> 사용자를
  만든다. 라인 8에서 <strong>CREATE DATABASE</strong>로
  <kbd>confluence</kbd> 데이터베이스를 생성한다. Confluence의 데이터베이스는
  인코딩과 Collation은 utf8로 설정해야 한다. 라인 10에서
  <strong>\l</strong> 명령어로 새로 생성한 confluence 데이터베이스를 확인한다.
  PostgreSQL에 기본적인 사용은
  <a href="https://www.bitneer.dev/wp/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/" target="_blank" rel="noopener noreferrer">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a
  >를 참고할 수 있다.
</p>
<h5>
  단계 4. 현재 사용하는 Confluence와 같은 버전의 Confluence를 새로 설치하기
</h5>
<p>
  새로 설치하는 Confluence는 <em>현재 사용하는 Confluence와 같은 버전</em>이어야
  한다. 그러나 설치 위치와 홈 디렉토리는 달라져야 한다. 다음과 같이 작업한다.
</p>
<p>1. 현재 사용하는 Confluence를 종료한다.</p>
<p>
  2. 마이그레이션에 실패할 시 빠르게 원래대로 복구하기 위해 기존 Confluence의
  설치 파일과 홈 디렉토리의 이름을 변경해 둔다.
</p>
<pre class="language-none">
<code># mv /opt/share/confluence /opt/share/confluence-old
# mv /var/local/lib/confluence /var/local/lib/confluence-old</code>
</pre>
<p>3. 새 Confluence를 위한 홈 디렉토리를 생성한다.</p>
<pre class="language-none line-numbers" data-line="4">
<code># mkdir /var/local/lib/confluence
# cd /var/local/lib
# chown confluence:confluence confluence
# chmod g-s confluence</code>
</pre>
<p>
  라인 4는 스티키 비트(sticky bit)를 사용하지 않으므로 제거한 것이다. 데비안에서
  /var/local 디렉토리의 그룹에 스티키 비트가 있어 /var/local/lib/confluence
  디렉토리에 스티키 비트가 붙는다. 여러분이 다른 Confluence 홈 디렉토리를
  사용한다면 무시하고 넘어간다.
</p>
<p>
  4. 기존 Confluece와 같은 버전의 TAR.GZ 압축 파일을 /opt/share에 복사한 후
  다음의 절차로 /opt/share/confluece에 위치하도록 압축을 푼다.
</p>
<pre class="language-none line-numbers" data-line="4-7">
<code># cd /opt/share
# tar zxvf atlassian-confluence-6.13.8.tar.gz
# mv atlassian-confluence-6.13.8 confluence
# chown -R root:root confluence
# chown -R confluence:confluence confluence/logs
# chown -R confluence:confluence confluence/temp
# chown -R confluence:confluence confluence/work</code>
</pre>
<p>
  라인 4에서 7까지 파일의 소유주와 그룹을 설정하는 이유는 보안 때문이다.
  Confluence 데몬이 쓰기 권한을 가져야만 하는 logs, temp, work 디렉토리 이외에는
  파일을 저장할 수 없도록 한다. 데몬(서비스)의 보안에 관해서는
  <a href="https://www.bitneer.dev/wp/confluence-jira-bitbucket%ec%9d%98-systemd-unit-%ec%84%a4%ec%a0%95/" target="_blank" rel="noopener noreferrer">Confluence, Jira, Bitbucket의 systemd unit 설정</a
  >에서 볼 수 있다.
</p>
<p>
  5. /opt/share/confluence/confluence/WEB-INF/classes/confluence-init.properties
  파일에서 다음과 같이 Confluence Home Directory를 지정한다.
</p>
<pre class="language-none">
<code>confluence.home=/var/local/lib/confluence</code>
</pre>
<p>
  6. (선택적) Confluence에 접속할 때 웹 브라우저에 따라 언어를 설정하지 않도록
  /opt/share/confluence/bin/setenv.sh 파일에 다음의 내용을 추가한다.
  Confluence에서 언어를 영어로 선택하여 항상 영문 메뉴가 나오도록 하기 위한
  것이다.
</p>
<pre class="language-none">
<code>CATALINA_OPTS="-Dconfluence.browser.language.enabled=false ${CATALINA_OPTS}"</code>
</pre>

<h5>
  단계 5. Confluence Setup Wizard를 진행하여 PostgreSQL로 마이그레이션 하기
</h5>
<p>
  1. 새로 설치한 Confluence 서버를 시작한 후 웹 브라우저로
  <kbd>http://192.168.1.10:8090/</kbd>에 접속하여 Confluence setup wizard를
  진행한다. IP 주소는 여러분에게 맞는 것으로 변경한다.
</p>
<p>
  2.
  <strong>Get apps</strong>에서 <strong>Production Installation</strong>을
  선택하고 <strong>Next</strong> 버튼을 클릭한다.
  <strong>Apps extend what Confluence can do. &#8230;</strong>에서
  <strong>Confluece Questions, Confluece Team Calendars</strong>를 디폴트인
  선택하지 않은 상태를 그대로 둔 채 <strong>Next</strong> 버튼을 클릭한다.
</p>
<p>
  3.
  <strong>License key</strong>에서 Confluence의 라이센스를 입력하고
  <strong>Next</strong> 버튼을 클릭한다. (<a href="https://my.atlassian.com/" target="_blank" rel="noopener noreferrer">https://my.atlassian.com/</a
  >에 접속하여 라이센스 키를 복사할 수 있다.)
</p>
<p>
  4.
  <strong>Set up your database</strong>에서 디폴트 선택인
  <strong>My own database</strong> 선택을 그대로 둔 채
  <strong>Next</strong> 버튼을 클릭한다. 다음의 설정을 한 후
  <strong>Test connection</strong> 버튼을 클릭한다. 데이터베이스 연결에 성공한
  메시지가 나오면 <strong>Next</strong> 버튼을 클릭한다.
</p>
<ul>
  <li>Database type: 디폴트 선택인 PostgreSQL을 그대로 둔다.</li>
  <li>Setup type: 디폴트 선택인 Simple을 그대로 둔다.</li>
  <li>
    Hostname: PostgreSQL이 설치된 시스템의 로컬 IP 주소를 입력한다. (예:
    192.168.1.10)
  </li>
  <li>Post: <kbd>5432</kbd>를 입력한다.</li>
  <li>
    Database name: 위에서 생성한 데이터베이스의 이름인 <kbd>confluecne</kbd>를
    입력한다.
  </li>
  <li>
    Username: 위에서 생성한 데이터베이스의 사용자 이름인 <kbd>confluence</kbd>를
    입력한다.
  </li>
  <li>Password: 위에서 생성한 데이터베이스의 &#8216;암호&#8217;를 입력한다.</li>
</ul>
<p>
  5. <strong>Load Content</strong>에서
  <strong>Restore From Backup</strong> 버튼을 클릭한다.
</p>
<p>
  6. <strong>Restore Data</strong> 화면에서
  <strong>Import form the home directory</strong>로 작업한다. 복원할
  xmlexport-20200524-215026-2.zip 파일의 크기가 25MB보다 크기 때문이다.
</p>
<p>
  6.1. 새로 설치한 Confluence 홈 디렉토리의 restore 디렉토리로 단계 2에서 생성한
  xmlexport-20200524-215026-2.zip 파일을 복사하기 위해 다음의 명령어를 실행한다.
</p>
<pre class="language-none">
<code># cp -a /var/local/lib/confluence-old/temp/xmlexport-20200524-215026-2.zip /var/local/lib/confluence/restore/</code>
</pre>
<p>
  cp의 <strong>-a</strong> 옵션은 파일의 속성인 소유자, 생성 날짜 등을 유지한 채
  복사하기 위한 것이다.
</p>
<p>
  6.2. 복사를 완료하였으면
  <strong>Import from the home directory</strong>의
  <strong>Import</strong> 버튼을 클릭한다. 에러 메시지와 함께
  xmlexport-20200524-215026-2.zip 파일이 보이면 선택하고 다시 한번
  <strong>Import</strong> 버튼을 클릭한다.
</p>
<p>
  6.3.
  <strong>Restore</strong> 과정이 진행된다. Restore 과정이 끝난 후
  <strong>Next</strong> 버튼을 클릭한다.
</p>
<p>
  7.
  <strong>Setup Successful</strong> 화면에서 <strong>Start</strong> 버튼을
  클릭한다.
</p>
<h5>단계 6. Atlassian Marketplace 앱을 다시 설치하기</h5>
<p>
  단계 1에서 메모해 두었던 앱들을 같은 버전으로 다시 설치한다. Confluence
  설정으로 들어가서
  <strong>ATLASSIAN MARKETPLACE &gt; Find new apps</strong>에서 앱을 검색할 수
  있다. Atlassian이 제공하는 앱은 이미 설치되어 있으므로 간단하게 Update만 한다.
</p>
<h5>단계 7. 새로 설치한 Confluence를 위한 설정을 한다.</h5>
<p>
  도메인의 URL 주소로 접속하기 위해 /opt/share/confluence/conf/server.xml 파일을
  수정한다. 나의 경우 Apache의 Proxy를 사용하기 때문에 다음과 같이 한다.
</p>
<p>
  &lt;Context&gt; 지시자의 <strong>path</strong>를 <kbd>/confluence</kbd>로
  설정한다.
</p>
<pre class="language-none">
<code>&lt;Context path="/confluence" docBase="../confluence" debug="0" reloadable="false" useHttpOnly="true"&gt</code>
</pre>
<p>
  디폴트 &lt;Connector&gt; 지시자는 주석 처리한다. HTTS 상의 Proxying인
  &lt;Connector&gt; 지시자의 주석을 제거하고 <strong>proxyName</strong>을
  <kbd>www.bitneer.dev</kbd>로 변경한다.
</p>
<pre class="language-markup line-numbers" data-line="5">
<code>&lt;Connector port=&quot;8090&quot; connectionTimeout=&quot;20000&quot; redirectPort=&quot;8443&quot;
           maxThreads=&quot;48&quot; minSpareThreads=&quot;10&quot;
           enableLookups=&quot;false&quot; acceptCount=&quot;10&quot; debug=&quot;0&quot; URIEncoding=&quot;UTF-8&quot;
           protocol=&quot;org.apache.coyote.http11.Http11NioProtocol&quot;
           scheme=&quot;https&quot; secure=&quot;true&quot; proxyName=&quot;www.bitneer.dev&quot; proxyPort=&quot;443&quot;/&gt;
</code></pre>
<p>
  Confluence를 다시 시작하고 웹 브라우저로 Confluence에 접속한다. Confluence
  설정에 들어가서 <strong>CONFIGURATION &gt; General Configuration</strong>의
  <strong>Server Base URL</strong>을 도메인 주소에 맞게 설정한다.
</p>
<h5>단계 8. 문제 점검 및 기존 파일 삭제하기</h5>
<p>
  다음의 명령어를 실행한 후 다른 ssh 연결 세션에서 Confluence를 시작, 종료하면서
  발생하는 로그를 검사한다.
</p>

<pre class="language-none">
<code># tail -100f /var/local/lib/confluence/logs/atlassian-confluence.log</code>
</pre>
<p>
  위의 atlassian-confluence.log에 Error 로그가 보인다면 Confluence 설정의
  <strong>ADMINISTRATION &gt; Troubleshooting and support tools</strong>의
  <strong>Log analyzer</strong>에서 문제를 해결할 수 있는지 확인한다. 해당 Error
  로그를 클릭하면 해결책을 제시하는 페이지에 접속할 수 있다.
</p>
<p>
  Confluence 설정의
  <strong>ADMINISTRATION &gt; Troubleshooting and support tools</strong>의
  <strong>Instance heath</strong>에 문제가 있는지 확인한다.
  atlassian-confluence.log에 Error 로그가 나오더라도
  <strong>Instance heath</strong>에서 모든 항목이 초록색으로 표시되어 있고
  <strong>Log analyzer</strong>에 해당 Error 로그가 나오지 않는다면 Confluence
  사용에 크게 문제를 일으키지는 않는 것으로 보인다.
</p>
<p>
  MySQL에서 PostgreSQL로 마이그레이션에 성공하였다면 기존의 Confluence 관련
  파일을 삭제한다.
</p>
<pre class="language-none">
<code># cd /opt/share/
# rm -rf confluence-old
# rm atlassian-confluence-6.13.8.tar.gz
# cd /var/local/lib/
# rm -rf confluence-old</code>
</pre>

<h5>관련 글</h5>
<ul>
  <li>
    <a href="https://www.bitneer.dev/wp/confluence-jira-bitbucket%ec%9d%98-systemd-unit-%ec%84%a4%ec%a0%95/" target="_blank" rel="noopener noreferrer">Confluence, Jira, Bitbucket의 systemd unit 설정</a
    >
  </li>
</ul>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://confluence.atlassian.com/conf613/supported-platforms-964961686.html" target="_blank" rel="noopener noreferrer">Supported Platforms &#8211; Confluence 6.13</a
    >
  </li>
  <li>
    <a href="https://confluence.atlassian.com/conf613/migrating-to-another-database-964961318.html" target="_blank" rel="noopener noreferrer">Migrating to Another Database &#8211; Confluence 6.13</a
    >
  </li>
  <li>
    <a href="https://confluence.atlassian.com/conf613/database-setup-for-postgresql-964961302.html" target="_blank" rel="noopener noreferrer">Database Setup for PostgreSQL &#8211; Confluence 6.13</a
    >
  </li>
</ul><p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/confluence-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-posgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Confluence 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Jira 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</title>
		<link>https://www.bitneer.dev/blog/jira-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Fri, 29 May 2020 17:07:14 +0000</pubDate>
				<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[네트워크와 시스템 관리]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[jira]]></category>
		<category><![CDATA[postgresql]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=570</guid>

					<description><![CDATA[<div data-nosnippet>Jira 서버의 MySQL을 PostgreSQL로 마이그레이션 한 작업 과정을 정리해 본다. 내가 사용하는 데비안 9(stretch)의 PostgreSQL 버전은 9.6이다. Jira 서버는 버전 7.13.0을 설치하고 있다. 먼저 이 버전의 Jira에서 지원하는 데이터베이스를 봐야 한다. Supported platforms &#8211; Jira Server 7.13을 보면 PostgreSQL 9.4, 9.5, 9.6을 지원하므로 마이그레이션을 진행할 수 있다. 아래에서 내가 사용하는 Jira 홈 디렉토리인 /var/local/lib/jira로 예를 들 것이다. 단계 1. XML ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/jira-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Jira 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  Jira 서버의 MySQL을 PostgreSQL로 마이그레이션 한 작업 과정을 정리해 본다. 내가
  사용하는 데비안 9(stretch)의 PostgreSQL 버전은 9.6이다. Jira 서버는 버전
  7.13.0을 설치하고 있다. 먼저 이 버전의 Jira에서 지원하는 데이터베이스를 봐야
  한다.
  <a href="https://confluence.atlassian.com/adminjiraserver0713/supported-platforms-964983071.html" target="_blank" rel="noopener noreferrer">Supported platforms &#8211; Jira Server 7.13</a
  >을 보면 PostgreSQL 9.4, 9.5, 9.6을 지원하므로 마이그레이션을 진행할 수 있다.
  아래에서 내가 사용하는 Jira 홈 디렉토리인 <kbd>/var/local/lib/jira</kbd>로
  예를 들 것이다.
</p>
<h5>단계 1. XML 포맷으로 Data를 백업하기</h5>
<p>
  Jira 서버에서 제공하는 백업 도구를 사용하여 XML 포맷의 파일로 Data를 백업한다.
  백업한 파일은 단계 4에서 PostgreSQL로 마이그레이션 하기 위해 사용할 것이다.
</p>
<ol>
  <li>Jira의 환경 설정인 <strong>System</strong>으로 들어한다.</li>
  <li>
    <strong>IMPORT AND EXPORT</strong>의 <strong>Backup System</strong>을
    클릭한다.
  </li>
  <li>
    <strong>Backup Jira data</strong> 화면에 &#8216;데이터베이스의 내용을 XML 포맷으로
    백업할 것이고 Jira 홈 디렉토리 안의 export 디렉토리에 저장할 것&#8217;이라고
    나온다. <strong>File name</strong>에 백업할 파일의 이름을 입력하고
    <strong>Backup</strong> 버튼을 클릭한다. 나는 <kbd>jira_backup</kbd>으로
    입력하였다.
  </li>
  <li>
    실행을 완료하면 자신이 입력한 파일명에 .zip 확장자를 붙여 내보냈음을
    알려준다. 나의 경우
    <kbd>/var/local/lib/jira/export/jira_backup.zip</kbd> 파일로 저장되었다.
  </li>
</ol>
<h5>단계 2. PostgreSQL의 데이터베이스 만들기</h5>
<p>
  Jira 서버에서 사용할 PostgreSQL 데이터베이스를 만든다. 다음은 psql
  클라이언트를 사용한 진행 과정이다.
</p>
<pre class="language-none" data-line="6,8,10,14">
<code># psql -h localhost -U postgres -d postgres
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=# CREATE ROLE jira WITH LOGIN PASSWORD &#039;암호 입력&#039;;
CREATE ROLE
postgres=# CREATE DATABASE jira WITH OWNER=jira ENCODING &#039;UTF8&#039; LC_COLLATE &#039;C&#039; LC_CTYPE &#039;C&#039; TEMPLATE template0;
CREATE DATABASE
postgres=# \l
                                 데이터베이스 목록
   이름    |  소유주  | 인코딩 |   Collate   |    Ctype    |      액세스 권한
-----------+----------+--------+-------------+-------------+-----------------------
 jira      | jira     | UTF8   | C           | C           |
 postgres  | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0 | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |          |        |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |          |        |             |             | postgres=CTc/postgres
(4개 행)</code>
</pre>
<p>
  라인 6에서 <strong>CREATE ROLE</strong>로 <kbd>jira</kbd> 사용자를 생성했다.
  라인 8에서 <strong>CREATE DATABASE</strong>로 <kbd>jira</kbd> 데이터베이스를
  만들었다. 주의해야 할 것은 Jira 서버는 LC_COLLATE와 LC_CTYPE을
  <strong>&#8216;C&#8217;</strong>로 설정해야 한다. 새 로케일로 데이터베이스를 만들려면
  <strong>template0</strong>을 사용해야 한다. 라인 10에서
  <strong>\l</strong> 명령어로 새로 만든 jira 데이터베이스를 확인한다.
  PostgreSQL의 기본적인 사용은
  <a href="https://www.bitneer.dev/wp/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/" target="_blank" rel="noopener noreferrer">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a
  >를 참고할 수 있다.
</p>
<h5>단계 3. JIRA setup을 실행하기 위한 준비</h5>
<p>Jira 서버의 설치 화면(JIRA setup)으로 진입하기 위한 작업을 한다.</p>
<ol>
  <li>Jira 서버를 종료한다.</li>
  <li>
    서버 종료 뒤가 백업의 적기이다. 현재 사용하고 있는 MySQL의 Jira
    데이터베이스와 Jira 홈 디렉토리를 백업해 둔다.
  </li>
  <li>
    Jira 홈 디렉토리(/var/local/lib/jira) 안의
    <strong>dbconfig.xml</strong> 파일을 삭제한다. 이 파일의 삭제로 JIRA
    setup으로 진입하는 것이다.
  </li>
</ol>
<h5>단계 4. JIRA setup을 사용하여 PostgreSQL로 마이그레이션 하기</h5>
<p>
  Jira 서버를 다시 시작하고 웹 브라우저로 접속하면 JIRA setup 화면이 나올
  것이다. PostgreSQL로 마이그레이션 하기 위해 다음과 같이 작업한다.
</p>
<ol>
  <li>
    Jira 설치 화면이 나오면 &#8216;<strong>직접 설정하겠습니다.</strong>&#8216;를 선택하고
    <strong>다음</strong> 버튼을 클릭한다.
  </li>
  <li>
    <strong>데이터베이스 설정</strong> 화면이 나오면
    <strong>내 데이터베이스(운영 환경에 권장)</strong>을 선택하고 다음의 내용을
    입력한다.
    <ul>
      <li>데이터베이스 유형: PostgreSQL</li>
      <li>
        호스트 이름: PostgreSQL을 설치한 시스템의 로컬 IP 주소를 입력한다. (예:
        192.168.1.20)
      </li>
      <li>포트: 디폴트 값인 5432를 그대로 둔다.</li>
      <li>
        데이터베이스: 위에서 생성한 데이터베이스의 이름인 <kbd>jira</kbd>를
        입력한다.
      </li>
      <li>
        사용자 아이디: 위에서 생성한 데이터베이스의 사용자 이름인
        <kbd>jira</kbd>를 입력한다.
      </li>
      <li>비밀번호: 위에서 생성한 데이터베이스의 &#8216;암호&#8217;를 입력한다.</li>
      <li>스키마: 디폴트 값인 public을 그대로 둔다.</li>
    </ul>
  </li>
  <li><strong>다음</strong> 버튼을 클릭한다.</li>
  <li>
    <strong>응용프로그램 속성을 설정하십시오.</strong> 화면에서 &#8216;<strong
      >&#8230; 데이터를 가져올 수 있습니다.</strong
    >&#8216;를 클릭한다.
  </li>
  <li>
    <strong>기존 데이터 가져오기</strong> 화면의 <strong>파일 이름</strong>에
    단계 1에서 생성한 <kbd>/var/local/lib/jira/export/jira_backup.zip</kbd>을
    입력하고 <strong>가져오기</strong> 버튼을 클릭한다.
  </li>
</ol>
<p>가져오기 작업이 끝나면 Jira의 Dashboards 화면이 나온다.</p>
<h5>데이터베이스의 마이그레이션 확인하기</h5>
<p>
  Jira 홈 디렉토리 안에 dbconfig.xml 파일이 새로 생성되고, PostgreSQL의 JDBC
  설정을 볼 수 있다.
</p>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://confluence.atlassian.com/adminjiraserver0713/administering-jira-server-7-13-applications-964983042.html" target="_blank" rel="noopener noreferrer">Administering Jira Server 7.13 applications</a
    >
    <ul>
      <li>
        <a href="https://confluence.atlassian.com/adminjiraserver0713/supported-platforms-964983071.html" target="_blank" rel="noopener noreferrer">Supported platforms &#8211; Jira Server 7.13</a
        >
      </li>
      <li>
        <a href="https://confluence.atlassian.com/adminjiraserver0713/switching-databases-964983111.html" target="_blank" rel="noopener noreferrer">Switching databases</a
        >
      </li>
      <li>
        <a href="https://confluence.atlassian.com/adminjiraserver0713/backing-up-data-964983964.html" target="_blank" rel="noopener noreferrer">Backing up data</a
        >
      </li>
      <li>
        <a href="https://confluence.atlassian.com/adminjiraserver0713/connecting-jira-applications-to-postgresql-964983092.html" target="_blank" rel="noopener noreferrer">Connecting Jira applications to PostgreSQL</a
        >
      </li>
    </ul>
  </li>
  <li>
    <a href="https://postgresql.kr/docs/9.6/manage-ag-templatedbs.html" target="_blank" rel="noopener noreferrer">템플릿 데이터베이스 &#8211; PostgreSQL 9.6.2 문서 22장 데이터베이스 관리</a
    >
  </li>
</ul><p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/jira-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Jira 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Bitbucket 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</title>
		<link>https://www.bitneer.dev/blog/bitbucket-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Thu, 28 May 2020 20:19:40 +0000</pubDate>
				<category><![CDATA[네트워크와 시스템 관리]]></category>
		<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[bitbucket]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[postgresql]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=546</guid>

					<description><![CDATA[<div data-nosnippet>데비안 시스템의 Bitbucket에서 MySQL을 PostgreSQL로 옮겼던 과정을 보여주려고 한다. 내가 사용하는 데비안 9(stretch)의 PostgreSQL 버전은 9.6이다. Bitbucket은 버전 7.2.3을 설치하고 있다. 먼저 이 버전의 Bitbucket에서 지원하는 데이터베이스를 볼 필요가 있다. Supported platforms &#8211; Bitbucket Server 7.2.x를 보면 PostgreSQL 9.4에서 11까지 지원하므로 마이그레이션을 진행할 수 있다. 작업을 진행하기 전에 기존의 MySQL의 데이터베이스와 Bitbucket 홈 디렉토리를 백업한다. 뒤에서 홈 디렉토리는 내가 사용하는 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/bitbucket-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Bitbucket 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  데비안 시스템의 Bitbucket에서 MySQL을 PostgreSQL로 옮겼던 과정을 보여주려고
  한다. 내가 사용하는 데비안 9(stretch)의 PostgreSQL 버전은 9.6이다. Bitbucket은
  버전 7.2.3을 설치하고 있다. 먼저 이 버전의 Bitbucket에서 지원하는
  데이터베이스를 볼 필요가 있다.
  <a href="https://confluence.atlassian.com/bitbucketserver/supported-platforms-776640981.html" target="_blank" rel="noopener noreferrer">Supported platforms &#8211; Bitbucket Server 7.2.x</a
  >를 보면 PostgreSQL 9.4에서 11까지 지원하므로 마이그레이션을 진행할 수 있다.
  작업을 진행하기 전에 기존의 MySQL의 데이터베이스와 Bitbucket 홈 디렉토리를
  백업한다. 뒤에서 홈 디렉토리는 내가 사용하는
  <kbd>/var/local/lib/bitbucket</kbd>으로 표시할 것이다.
</p>
<h5>PostgreSQL에서 데이터베이스 만들기</h5>
<p>
  Bitbucket 서버에서 사용할 PostgreSQL의 데이터베이스를 만든다. 다음은 psql
  클라이언트를 사용한 진행 과정이다.
</p>
<pre class="language-none" data-line="6,8,10,14">
<code># psql -h localhost -U postgres -d postgres
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=# CREATE ROLE bitbucket WITH LOGIN PASSWORD &#039;원하는 암호 입력&#039;;
CREATE ROLE
postgres=# CREATE DATABASE bitbucket WITH ENCODING=&#039;UTF8&#039; OWNER=bitbucket;
CREATE DATABASE
postgres=# \l
                                  데이터베이스 목록
    이름    |   소유주   | 인코딩 |   Collate   |    Ctype    |      액세스 권한
------------+------------+--------+-------------+-------------+-----------------------
 bitbucket  | bitbucket  | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 confluence | confluence | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 jira       | jira       | UTF8   | C           | C           |
 postgres   | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0  | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
            |            |        |             |             | postgres=CTc/postgres
 template1  | postgres   | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
            |            |        |             |             | postgres=CTc/postgres
(6개 행)

postgres=#</code>
</pre>
<p>
  라인 6에서 <strong>CREATE ROLE</strong>로 <kbd>bitbucket</kbd> 사용자를
  만든다. 라인 8에서 <strong>CREATE DATABASE</strong>로
  <kbd>bitbucket</kbd> 데이터베이스를 생성한다. Bitbucket의 데이터베이스는 UTF-8
  문자 집합을 사용하도록 설정해야 한다. 라인 10에서 <strong>\l</strong> 명령어로
  새로 생성한 bitbucket 데이터베이스를 확인한다. PostgreSQL의 기본적인 사용은
  <a href="https://www.bitneer.dev/wp/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/" target="_blank" rel="noopener noreferrer">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a
  >에서 다루었다.
</p>
<h5>Database Migration Wizard를 사용하여 데이터베이스 마이그레이션 하기</h5>
<p>
  웹 브라우저로 Bitbucket 서버에 접속한다. 설정 아이콘을 클릭하여 Administration
  페이지로 들어간 후 다음의 작업을 진행한다.
</p>
<p>1. <strong>Settings &gt; Database</strong>를 클릭한다.</p>
<p>2. <strong>Migrate database</strong> 버튼을 클릭한다.</p>
<img decoding="async"
  src="https://www.bitneer.dev/wp/wp-content/uploads/2020/05/202005290219.png"
  alt="Migrate Database to PostgreSQL"
/>

<p>3. Migrate Database에서 다음의 설정을 한다.</p>
<ul>
  <li>Database Type: 디폴트 선택인 PostgreSQL을 그대로 둔다.</li>
  <li>
    Hostname; PostgreSQL을 설치한 시스템의 로컬 IP 주소를 입력한다. (예:
    192.168.1.10)
  </li>
  <li>Port: PostgreSQL의 포트를 변경하지 않았다면 디폴트 값을 그대로 둔다.</li>
  <li>
    Database name: 위에서 생성한 데이터베이스의 이름인 <kbd>bitbucket</kbd>을
    입력한다.
  </li>
  <li>
    Database username: 위에서 생성한 데이터베이스의 사용자 이름인
    <kbd>bitbucket</kbd>을 입력한다.
  </li>
  <li>Database password: 위에서 생성한 데이터베이스의 &#8216;암호&#8217;를 입력한다.</li>
</ul>
<p>
  설정을 마친 후 <strong>Start Migration</strong> 버튼을 클릭하면 마이그레이션을
  진행한다.
</p>
<p>4. 마이그레이션 진행을 완료하면 성공 메시지가 나온다.</p>

<h5>데이터베이스의 마이그레이션 확인하기</h5>
<p>
  PostgreSQL로 변경했는지 확인하려면 Bitbucket 홈 디렉토리의
  bitbucket.properties 파일을 본다. 파일 경로는
  <kbd>/var/local/lib/bitbucket/shared/bitbucket.properties</kbd>이다. 파일에서
  MySQL의 JDBC 설정은 주석으로 처리하고 PostgreSQL을 추가한 것을 볼 수 있을
  것이다.
</p>
<p>
  Database Migration Wizard는 마이그레이션할 때 dump 파일을 생성한다.
  <kbd>/var/local/lib/bitbucket/export</kbd> 디렉토리 안에 .zip 확장자로
  만들어지는데 삭제하여도 무방하다.
</p>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://confluence.atlassian.com/bitbucketserver/supported-platforms-776640981.html" target="_blank" rel="noopener noreferrer">Supported platforms &#8211; Bitbucket Server 7.2.x</a
    >
  </li>
  <li>
    <a href="https://confluence.atlassian.com/bitbucketserver/connecting-bitbucket-server-to-postgresql-776640389.html" target="_blank" rel="noopener noreferrer">Connecting Bitbucket Server to PostgreSQL</a
    >
  </li>
  <li>
    <a href="https://confluence.atlassian.com/bitbucketserver/connecting-bitbucket-server-to-an-external-database-776640378.html#ConnectingBitbucketServertoanexternaldatabase-migration" target="_blank" rel="noopener noreferrer">Connecting Bitbucket Server to an external database</a
    >
  </li>
</ul><p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/bitbucket-%ec%84%9c%eb%b2%84%ec%9d%98-mysql%ec%9d%84-postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0/">Bitbucket 서버의 MySQL을 PostgreSQL로 마이그레이션 하기</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</title>
		<link>https://www.bitneer.dev/blog/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Fri, 22 May 2020 19:56:53 +0000</pubDate>
				<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[postgresql]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=447</guid>

					<description><![CDATA[<div data-nosnippet>PostgreSQL의 설치와 설정, 간단한 튜닝에 대해 데비안의 PostgreSQL 설치와 설정에서 다루었다. 이 페이지에서는 PostgreSQL의 실제적인 사용인 데이터베이스와 사용자 생성, 백업 및 복구에 대해 살펴본다. 데이터베이스와 사용자 생성 PostgreSQL은 데이터베이스와 사용자 생성을 위한 createdb, createuser 명령어를 제공한다. 여기서는 SQL문을 사용하여 데이터베이스와 사용자를 생성하는 방법을 볼 것이다. 먼저 사용자 생성을 보자. PostgreSQL은 데이터베이스에 대한 접근 권한을 롤(role) 개념으로 다룬다. 롤은 어떻게 설정하느냐에 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  PostgreSQL의 설치와 설정, 간단한 튜닝에 대해
  <a href="https://www.bitneer.dev/wp/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/" target="_blank" rel="noopener noreferrer">데비안의 PostgreSQL 설치와 설정</a
  >에서 다루었다. 이 페이지에서는 PostgreSQL의 실제적인 사용인 데이터베이스와
  사용자 생성, 백업 및 복구에 대해 살펴본다.
</p>
<h5>데이터베이스와 사용자 생성</h5>
<p>
  PostgreSQL은 데이터베이스와 사용자 생성을 위한 createdb, createuser 명령어를
  제공한다. 여기서는 SQL문을 사용하여 데이터베이스와 사용자를 생성하는 방법을 볼
  것이다. 먼저 사용자 생성을 보자. PostgreSQL은 데이터베이스에 대한 접근 권한을
  롤(role) 개념으로 다룬다. 롤은 어떻게 설정하느냐에 따라 <em>사용자</em> 또는
  사용자들의 <em>그룹</em>으로 생각할 수 있다. 롤은 롤들을 포함할 수 있다.
  클러스터 개념과 비슷하게 대규모 조직을 위한 것이다.
</p>
<p>
  사용자를 만들기 위해 선호하는 pgAdmin, DataGirp 등과 같은 PostgreSQL
  클라이언트에서 다음의 SQL문을 실행한다. 예제를 쉽게 보여주고 세션의 개념을
  설명하기 위해 나는 psql 클라이언트를 사용할 것이다.
</p>
<pre class="language-none line-numbers" data-line="6,8,10,12,16">
<code># psql -h localhost -U postgres -d postgres
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=# CREATE USER mydb;
CREATE ROLE
postgres=# CREATE ROLE developer LOGIN;
CREATE ROLE
postgres=# SELECT * FROM pg_roles;
...
postgres=# DROP ROLE mydb;
DROP ROLE
postgres=# DROP ROLE developer;
DROP ROLE
postgres=# CREATE ROLE testdb_user WITH LOGIN PASSWORD &#039;/root/.pgpass 파일에서 설정한 개발이나 응용프로그램에서 사용할 암호 입력&#039;;
CREATE ROLE</code>
</pre>
<p>
  라인 8에 있는 SQL문처럼 <strong>CREATE ROLE</strong>에
  <strong>LOGIIN</strong>이 들어가면 사용자를 생성한다는 의미이다. 라인 6의
  <strong>CREATE USER</strong>는 디폴트로 로그인을 가정하기 때문에
  <strong>LOGIN</strong>을 생략할 수 있다. 즉, 위의 라인 6과 8은 사용자를
  만든다는 점에서 같은 SQL문이다. 라인 10의
  <strong>SELECT * FROM pg_roles;</strong>로 롤을 확인할 수 있다. 라인 12와
  14에서 <strong>DROP ROLE</strong>로 롤을 삭제한다. 라인 16의 마지막의
  SQL문처럼 보통은 암호를 설정하여 사용자를 생성한다.
</p>
<p>
  <strong>.pgpass</strong> 파일 설정은
  <a href="https://www.bitneer.dev/wp/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/" target="_blank" rel="noopener noreferrer">데비안의 PostgreSQL 설치와 설정</a
  >에서 다루었다. <strong>.pgpass</strong> 파일은 로컬시스템에서 &#8216;su -s
  /bin/bash postgres&#8217; 명령문 없이 psql을 사용하기 위한 것이다. pgAdmin, DataGrip
  등의 클라이언트를 사용하여 원격에서 접근하는 경우는 다른 암호를 사용할 수
  있다.
</p>
<p>다음으로 testdb_user 사용자가 사용할 데이터베이스를 생성해 보자.</p>
<pre class="language-none line-numbers" data-line="1,3,15,17,18,20">
<code>postgres=# CREATE DATABASE testdb WITH ENCODING=&#039;UTF8&#039; OWNER=testdb_user;
CREATE DATABASE
postgres=# \l
                                  데이터베이스 목록
   이름    |   소유주    | 인코딩 |   Collate   |    Ctype    |      액세스 권한
-----------+-------------+--------+-------------+-------------+-----------------------
 postgres  | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0 | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |             |        |             |             | postgres=CTc/postgres
 template1 | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |             |        |             |             | postgres=CTc/postgres
 testdb    | testdb_user | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
(4개 행)

postgres=# \c testdb
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
접속정보: 데이터베이스=&quot;testdb&quot;, 사용자=&quot;postgres&quot;.
testdb=# \c testdb testdb_user
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
접속정보: 데이터베이스=&quot;testdb&quot;, 사용자=&quot;testdb_user&quot;.
testdb=&gt;</code>
</pre>
<p>
  라인 1의 첫 번째 SQL문에서 <strong>CREATE DATABASE</strong>로 testdb
  데이터베이스를 생성하였다. 라인 3처럼 <strong>\l</strong> 명령어로
  데이터베이스의 목록을 확인할 수 있다. psql은 역슬래시(\)를 가지는 명령문을
  제공한다. <strong>\?</strong> 실행으로 명령문에 대한 도움말을 볼 수 있다. 라인
  15처럼 <strong>\c</strong> 명령어로 testdb로 연결하는 세션을 만든다.
  PostgreSQL은 세션 연결로 데이터베이스를 이동한다. MySQL, Microsoft SQL
  Server에서 데이터베이스 변경에 사용하는 &#8216;USE database_name;&#8217;문이 없다.
  Oracle과 비슷하게 세션의 개념을 사용한다. 이러한 세션의 연결과 종료로
  데이터베이스를 이동하려면 클라이언트에서 기능을 제공해야 하는데 psql에서는
  <strong>\c</strong> 명령어이다.
</p>
<p>
  라인 15의 첫 번째 \c 명령은 postgres 관리자에서 사용자 지정 없이
  <strong>\c testdb</strong> 명령을 실행하였다. 라인 17의 접속정보를 보면 사용자
  postgres로 접속한 상태다. 이 상태에서 테이블을 만들면 그 테이블의 소유주는
  postgres이고 testdb_user 사용자는 그 테이블에 접근할 수 없다. 따라서 라인 18의
  <strong>\c testdb testdb_user</strong>처럼 사용자를 지정하여 testdb_user로
  세션을 연결해야 한다.
</p>
<p>
  백업 및 복구 예제를 위해 testdb 데이터베이스에 테이블을 만들고 몇몇 값을
  입력해 보자.
</p>
<pre class="language-none line-numbers" data-line="1,3,7,14,18">
<code>testdb=&gt; CREATE TABLE students(id INTEGER, l_name VARCHAR(20), f_name VARCHAR(20));
CREATE TABLE
testdb=&gt; INSERT INTO students(id, l_name, f_name) VALUES (1, &#039;홍&#039;, &#039;길동&#039;);
INSERT 0 1
testdb=&gt; INSERT INTO students(id, l_name, f_name) VALUES (2, &#039;김&#039;, &#039;길상&#039;);
INSERT 0 1
testdb=&gt; SELECT * FROM students;
 id | l_name | f_name
----+--------+--------
  1 | 홍     | 길동
  2 | 김     | 길상
(2개 행)

testdb=&gt; \dt
         릴레이션(relation) 목록
 스키마 |   이름   |  종류  |   소유주
--------+----------+--------+-------------
 public | students | 테이블 | testdb_user
(1개 행)</code>
</pre>
<p>
  라인 1의 첫 번째 SQL문에서 <strong>CREATE TABLE</strong>로 students 테이블을
  만들었다. 라인 3과 5에서 <strong>INSERT INTO</strong>를 사용하여 students
  테이블에 데이터를 넣어주었다. 라인 7에서 <strong>SELECT</strong>를 사용하여
  students 테이블의 값을 출력하였다. 라인 14의 <strong>\dt</strong> 명령어는
  테이블 목록을 보여준다. 라인 18에서 보듯이 testdb_user 사용자의 세션에서
  students 테이블을 만들었기 때문에 소유주는 testdb_user이다.
</p>
<h5>백업 및 복구</h5>
<p>
  PostgreSQL은 백업 및 복구를 위해 pg_dump와 pg_restore 명령어를 제공한다.
  testdb 데이터베이스를 백업하기 위해 다음의 명령어를 실행한다.
</p>
<pre class="language-none">
<code># pg_dump -Fc -h localhost -U postgres -d testdb -f /root/testdb.dump</code>
</pre>
<p>
  pg_dump에서 -F 옵션은 백업 파일의 포맷을 선택하는 것으로 c(custom)를 사용해야
  pg_restore 명령어로 복구할 수 있다. <strong>-Fc</strong> 옵션은 디폴트로
  파일을 압축한다.
</p>
<p>
  복구를 테스트하기 위해 psql에서 기존에 존재하는 testdb 데이터베이스를 삭제하고
  다시 생성한다.
</p>
<pre class="language-none line-numbers" data-line="1,4,6,17,31,34">
<code>testdb=&gt; \c postgres postgres
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
접속정보: 데이터베이스=&quot;postgres&quot;, 사용자=&quot;postgres&quot;.
postgres=# DROP DATABASE testdb;
DROP DATABASE
postgres=# \l
                                 데이터베이스 목록
   이름    |  소유주  | 인코딩 |   Collate   |    Ctype    |      액세스 권한
-----------+----------+--------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0 | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |          |        |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |          |        |             |             | postgres=CTc/postgres
(3개 행)

postgres=# CREATE DATABASE testdb WITH ENCODING=&#039;UTF8&#039; OWNER=testdb_user;
CREATE DATABASE
postgres=# \l
                                  데이터베이스 목록
   이름    |   소유주    | 인코딩 |   Collate   |    Ctype    |      액세스 권한
-----------+-------------+--------+-------------+-------------+-----------------------
 postgres  | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
 template0 | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |             |        |             |             | postgres=CTc/postgres
 template1 | postgres    | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 | =c/postgres          +
           |             |        |             |             | postgres=CTc/postgres
 testdb    | testdb_user | UTF8   | ko_KR.UTF-8 | ko_KR.UTF-8 |
(4개 행)

postgres=# \c testdb testdb_user
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
접속정보: 데이터베이스=&quot;testdb&quot;, 사용자=&quot;testdb_user&quot;.
testdb=&gt; \dt
릴레이션(relation) 없음.</code>
</pre>
<p>
  첫 번째 줄에서 <strong>\c</strong> 명령어로 postgres 데이터베이스-postgres
  사용자의 세션으로 변경하여 testdb에 대한 세션을 끊었다. 세션을 연결한
  상태에서는 데이터베이스를 삭제할 수 없다. 라인 4에서
  <strong>DROP DATABASE</strong>를 사용하여 testdb 데이터베이스를 삭제했다. 라인
  6에서 <strong>\l</strong> 명령어로 testdb 데이터베이스를 삭제하였는지
  확인하였다. 라인 17에서 <strong>CREATE DATABASE</strong>로 복구에 사용할
  testdb 데이터베이스를 새로 생성하였다. 라인 31에서
  <strong>\c</strong> 명령어로 testdb 데이터베이스- testdb_user 사용자의
  세션으로 이동하였다. 마지막으로 라인 34에서 <strong>\dt</strong> 명령어를
  사용하여 테이블이 없는 것을 확인한다.
</p>
<p>testdb 데이터베이스를 복구하기 위해 다음의 명령어를 실행한다.</p>
<pre class="language-none line-numbers" data-line="1">
<code># pg_restore -v -h localhost -U postgres -d testdb /root/testdb.dump
pg_restore: 리스토어 작업을 위해 데이터베이스에 접속합니다
pg_restore: SCHEMA &quot;public&quot; 만드는 중
pg_restore: COMMENT &quot;SCHEMA public&quot; 만드는 중
pg_restore: EXTENSION &quot;plpgsql&quot; 만드는 중
pg_restore: COMMENT &quot;EXTENSION plpgsql&quot; 만드는 중
pg_restore: TABLE &quot;public.students&quot; 만드는 중
pg_restore: &quot;public.students&quot; 테이블의 자료를 처리 중</code>
</pre>
<p>
  pg_restore에서 <strong>-v</strong> 옵션은 진행 상황을 보기 위한 것이다. 이제
  psql에서 복구가 되었는지 확인해 보자.
</p>
<pre class="language-none" data-line="1,8">
<code>testdb=&gt; \dt
         릴레이션(relation) 목록
 스키마 |   이름   |  종류  |   소유주
--------+----------+--------+-------------
 public | students | 테이블 | testdb_user
(1개 행)

testdb=&gt; SELECT * FROM students;
 id | l_name | f_name
----+--------+--------
  1 | 홍     | 길동
  2 | 김     | 길상
(2개 행)</code>
</pre>
<p>
  라인 1과 8에서 <strong>\dt</strong> 명령어로 테이블이 존재는지와
  <strong>SELECT</strong>로 students 테이블의 값을 확인하였다. 복구에 성공한
  것을 볼 수 있다.
</p>
<p>
  백업 및 복구는 복잡하고 어려운 주제이다. 백업한 시점 이후에 추가하거나 변경한
  데이터는 복구가 힘들 수 있다. 또한, 아주 큰 데이터베이스를 복구한다면 사용자에
  대한 서비스를 오랜 시간 동안 중단해야 한다. 이런 문제를 해결하려면 많은 노력을
  들여야 하고 전문적인 상용 제품들도 있다. 개인적인 사용이라면 백업 주기를 짧게
  하여 데이터 손실을 적게 하는 것이 차선의 선택일 것이다.
</p>
<h5>관련 글</h5>
<ul>
  <li>
    <a href="https://www.bitneer.dev/wp/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/" target="_blank" rel="noopener noreferrer">데비안의 PostgreSQL 설치와 설정</a
    >
  </li>
</ul>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://www.postgresql.org/docs/manuals/" target="_blank" rel="noopener noreferrer">PostgreSQL: Manuals</a
    >
  </li>
  <li>
    <a href="https://www.pgadmin.org/" target="_blank" rel="noopener noreferrer">pgAdmin PostgreSQL Tools</a
    >
  </li>
  <li>
    <a href="https://www.jetbrains.com/ko-kr/datagrip/features/" target="_blank" rel="noopener noreferrer">기능 및 스크린샷 &#8211; DataGrip</a
    >
  </li>
</ul>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>데비안의 PostgreSQL 설치와 설정</title>
		<link>https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/</link>
		
		<dc:creator><![CDATA[Choi Kyung-sik]]></dc:creator>
		<pubDate>Fri, 22 May 2020 19:53:04 +0000</pubDate>
				<category><![CDATA[데이터베이스 시스템]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[postgresql]]></category>
		<guid isPermaLink="false">https://www.bitneer.dev/?p=337</guid>

					<description><![CDATA[<div data-nosnippet>내가 사용하고 있는 Confluence, Jira, Bitbucket의 MySQL을 PostgreSQL로 변경하기로 마음먹고 학습을 진행했다. 그간에 얻은 PostgreSQL의 설치, 설정, 튜닝, 데이터베이스와 사용자 생성, 백업 및 복구 등을 전반적으로 정리해 본다. 이 페이지에서는 설치, 설정, 튜닝에 대해서 다룬다. 나머지 내용은 PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구로 이어진다. PostgreSQL을 처음 접하는 분들에게 도움이 되었으면 한다. PostgreSQL 설치 PostgreSQL의 라이센스는 자유를 추구하는 데비안과 잘 ...</div>
<p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/">데비안의 PostgreSQL 설치와 설정</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>
  내가 사용하고 있는 Confluence, Jira, Bitbucket의 MySQL을 PostgreSQL로
  변경하기로 마음먹고 학습을 진행했다. 그간에 얻은 PostgreSQL의 설치, 설정,
  튜닝, 데이터베이스와 사용자 생성, 백업 및 복구 등을 전반적으로 정리해 본다. 이
  페이지에서는 설치, 설정, 튜닝에 대해서 다룬다. 나머지 내용은
  <a href="https://www.bitneer.dev/wp/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a
  >로 이어진다. PostgreSQL을 처음 접하는 분들에게 도움이 되었으면 한다.
</p>
<h5>PostgreSQL 설치</h5>
<p>
  PostgreSQL의 라이센스는 자유를 추구하는 데비안과 잘 맞는다. PostgreSQL은
  데비안의 주요 패키지 중의 하나이기 때문에 다음과 같이 한 줄의 명령어로
  설치한다.
</p>
<pre class="language-none">
<code># apt install postgresql postgresql-client</code>
</pre>
<p>설치 후 PostgreSQL 관련 파일의 위치는 다음과 같다.</p>
<ul>
  <li>설정 파일: /etc/postgresql/[version]/[cluster]/</li>
  <li>실행 파일: /usr/lib/postgresql/[version]</li>
  <li>데이타 파일: /var/lib/postgresql/[version]/[cluster]</li>
  <li>
    로그 파일: /var/log/postgresql 디렉토리 안의
    postgresql-[version]-[cluster].log
  </li>
</ul>
<p>
  내가 사용하는 데비안 9(stretch)에서 PostgreSQL 버전은 9.6이다. 앞으로 나올
  파일의 경로는 9.6을 기준으로 서술한다. PostgreSQL은 클러스터로 데이터베이스를
  관리한다. 간단하게 &#8216;클러스터 &gt; 데이터베이스 &gt; 테이블&#8217;의 순서로 그려볼 수
  있다. 여러 개의 클러스터가 존재할 수 있고 한 클러스터 내에 여러 개의
  데이터베이스를 가질 수 있다. 클러스터는 아마존 클라우드와 같이 대용량을 위한
  것이다. 개인이라면 하나의 클러스터로도 충분할 것이다.
</p>
<p>
  데비안은 pg_ctl을 pg_ctlcluster로 대체한다. pg_ctlcluster는 Perl 스크립트
  파일이고 내부에서 pg_ctl을 사용한다. pg_ctlcluster는 PostgreSQL의 다양한
  버전과 여러 클러스터를 효율적으로 관리하기 위한 것이다.
</p>
<p>
  데비안에서 PostgreSQL의 init.d 시작 스크립트는 /etc/init.d/postgresql이다. 이
  시작 스크립트 안에서 pg_ctlcluster를 호출한다. PostgreSQL의 시작과 종료는
  systemctl을 사용하거나 다음과 같이 init.d 시작 스크립트를 실행할 수 있다.
</p>
<pre class="language-none line-numbers" data-line="1,3,5">
<code># /etc/init.d/postgresql stop
[ ok ] Stopping postgresql (via systemctl): postgresql.service.
# /etc/init.d/postgresql start
[ ok ] Starting postgresql (via systemctl): postgresql.service.
# /etc/init.d/postgresql restart 
[ ok ] Restarting postgresql (via systemctl): postgresql.service.
/etc/init.d/postgresql reload
[ ok ] Reloading postgresql configuration (via systemctl): postgresql.service.
# /etc/init.d/postgresql status
...</code>
</pre>

<h5>사용자 접근 설정</h5>
<p>
  디폴트 데이타베이스와 사용자는 postgres이다. 데이타베이스 관리는 postgres
  사용자로 하여야 한다. root 계정에서 다음의 명령어로 postgres 사용자로
  변경한다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># su -s /bin/bash postgres
$ id
uid=115(postgres) gid=124(postgres) groups=124(postgres),112(ssl-cert)</code>
</pre>
<p>
  id 명령어로 현재의 사용자가 postgres인지 확인할 수 있다. postgres로 사용자
  변경후 psql 클라이언트 프로그램을 실행한다.
</p>
<pre class="language-none">
<code>$ psql</code>
</pre>
<p>
  root에서 postgres로 사용자를 전환하는
  <em>su 명령어를 사용하지 않고</em> psql을 직접 실행하려면 다음과 같이 하여야
  한다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># psql -h localhost -U postgres -d postgres
postgres 사용자의 암호:</code>
</pre>
<p>
  postgres 사용자의 암호를 묻는 메시지가 나온다. 데비안에서는 디폴트로 postgres
  사용자의 암호가 없다. &lt;Ctrl + C&gt; 키를 눌러 우선은 빠져나온다.
</p>
<p>
  데비안의 PostgreSQL은 로컬 시스템에서 peer 인증(authentication)을 사용한다.
  peer 인증은 PostgreSQL 사용자와 동일한 이름을 가지는 로컬 계정으로 로컬
  시스템에 로그인하면 암호 없이 데이터베이스를 사용할 수 있다. 이러한 설정은
  /etc/postgresql/9.6/main/pg_hba.conf에서 확인할 수 있다.
</p>
<pre
  class="language-none line-numbers"
  data-line="8"
  data-label="/etc/postgresql/9.6/main/pg_hba.conf"
>
<code># Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD
# &quot;local&quot; is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
...</code>
</pre>
<p>
  위 설정을 보면 로컬 시스템(127.0.0.1/32)에 <em>로그인하지 않고</em>(host)
  접근하려면 암호를 사용해야 한다. METHOD가 md5인 경우 암호를 사용한다는
  의미이다. 로컬 시스템에서 사용자가 아니라 응용프로그램이 PostgreSQL
  데이터베이스에 접속할 때 적용될 것이다. 또는 위에서 보았듯 root 계정에서
  PostgreSQL 사용자로 전환하는 su를 사용하지 않고 psql, pg_dump 등을 사용할 때
  암호를 사용해야 한다.
</p>
<p>
  PostgreSQL의 관리자 권한을 가지는 postgres 사용자에 암호를 설정하려면 psql
  클라이언트에서 다음의 SQL문을 실행한다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code>postgres=# ALTER USER postgres PASSWORD &#039;원하는 암호 입력&#039;;
ALTER ROLE
postgres=# \q</code>
</pre>
<p>
  SQL 실행 후 ALTER ROLE 확인 메시지가 나오면 성공한 것이다.
  <strong>\q</strong> 명령어를 실행하여 psql을 종료한다.
</p>
<p>
  root 계정으로 다음과 같이 psql을 다시 실행하고 설정한 암호를 입력하여 접속에
  성공하는지 확인해 본다.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># psql -h localhost -U postgres -d postgres
postgres 사용자의 암호: &lt;설정한 암호 입력&gt;
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=#</code>
</pre>
<p>
  매번 암호를 입력하는 것은 귀찮은 작업이다. 특히 백업에 사용하는 pg_dump를
  스크립트에서 사용할 때 암호가 노출된다. pg_dump를 한 번 실행해 보자.
</p>
<pre class="language-none line-numbers" data-line="1">
<code># pg_dump -Fc -h localhost -U postgres -d postgres -f /root/postgres_`date +%F`.dump
암호:</code>
</pre>
<p>스크립트에서 암호를 입력하지 않고 실행하려면 다음과 같이 해야 한다.</p>
<pre class="language-bash" data-label="pg_backup.sh">
<code>#!/bin/bash
export PGPASSWORD=&quot;yourpassword&quot;
pg_dump -Fc -h localhost -U postgres -d postgres -f /root/postgres_`date +%F`.dump</code>
</pre>
<p>이를 해결하기 위해 다음의 내용을 가지는 /root/.pgpass 파일을 생성한다.</p>
<pre
  class="language-none line-numbers"
  data-line="2"
  data-label="/root/.pgpass"
>
<code>localhost:5432:*:postgres:&lt;관리자인 postgres의 암호를 입력&gt;
localhost:5432:*:*:&lt;개발이나 응용프로그램에서 사용할 암호 입력&gt;</code>
</pre>
<p>
  위의 내용은 <strong>hostname:port:database:username:password</strong>를
  의미한다. 별표 문자 *는 와일드카드로 &#8216;모든&#8217;을 뜻한다. 마지막의 password를
  제외하고 별표 문자를 사용할 수 있다. 두 번째 줄에서 개발이나 다른
  응용프로그램에서 사용할 데이터베이스의 암호를 따로 설정해 주었다. 일반적으로
  개발이나 응용프로그램은 설정 파일에 암호를 저장하는 경우가 빈번하기 때문에
  사용하는 데이터베이스의 암호가 노출되기 쉽다. 관리자 암호와는 다른 암호를
  사용하여 관리자의 암호를 보호하기 위해 두 번째 줄을 추가한 것이다. root 외
  다른 사용자가 .pgpass 파일 안의 내용을 보지 못하도록 다음의 명령어를 실행한다.
</p>

<pre class="language-none">
<code># chmod 600 /root/.pgpass</code>
</pre>
<p>
  다시 root 계정으로 pg_dump와 psql을 실행하면 암호를 묻지 않는 것을 확인할 수
  있다.
</p>
<pre class="language-none">
<code># pg_dump -Fc -h localhost -U postgres -d postgres -f /root/postgres_`date +%F`.dump
# psql -h localhost -U postgres -d postgres
psql (9.6.17)
SSL 연결정보 (프로토콜: TLSv1.2, 암호화기법: ECDHE-RSA-AES256-GCM-SHA384, 비트: 256, 압축: off)
도움말을 보려면 &quot;help&quot;를 입력하십시오.

postgres=#</code>
</pre>

<h5>원격 접속을 위한 설정</h5>
<p>
  시스템 외부에서 pgAdmin, DataGrip 등의 프로그램을 사용하여 원격으로 접속하려면
  몇 가지 설정을 해야 한다. PostgreSQL은 기본값으로 포트 5432를 사용한다.
  데비안에서 포트 5432는 디폴트로 로컬 주소(127.0.0.1)로 바인딩한다. 다음의
  명령어로 확인할 수 있다.
</p>
<pre class="language-none">
<code># netstat -nlt | grep 5432
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN</code>
</pre>
<p>
  따라서 시스템 외부에서 접근할 수 없다. 시스템 외부에서 접근할 수 있도록
  허용하려면 /etc/postgresql/9.6/main/postgresql.conf 파일에 다음의 내용을
  설정한다.
</p>
<pre
  class="language-none line-numbers"
  data-line="1"
  data-label="/etc/postgresql/9.6/main/postgresql.conf"
>
<code>listen_addresses = &#039;*&#039;</code>
</pre>
<p>
  로컬 네트워크에 있는 컴퓨터가 접근할 수 있도록 허용하려면
  /etc/postgresql/9.6/main/pg_hba.conf에 다음의 내용을 추가한다. 로컬 네트워크
  대역의 주소(192.168.1.0/24)는 여러분에게 맞는 값을 넣어준다.
</p>
<pre
  class="language-none line-numbers"
  data-label="/etc/postgresql/9.6/main/pg_hba.conf"
  data-start="2"
  data-line="2"
>
<code>host    all             all             192.168.1.0/24         md5</code>
</pre>
<p>모든 설정을 마쳤으면 PostgreSQL을 다시 시작한다.</p>
<pre class="language-none line-numbers" data-start="3">
<code># /etc/init.d/postgresql restart</code>
</pre>

<h5>PostgreSQL의 기본적인 튜닝</h5>
<p>
  PostgreSQL은 오래된 시스템을 지원하기 위한 설정값을 디폴트로 가진다. 전문적인
  튜닝은 아니지만 약간의 설정을 변경하는 것으로도 많은 성능 향상을 가져온다.
  다음의 사이트에서 설정값에 대한 힌트를 얻을 수 있다.
</p>
<ul>
  <li>
    <a href="https://pgtune.leopard.in.ua/#/" target="_blank" rel="noopener noreferrer">PGTune</a
    >
  </li>
  <li>
    <a href="https://www.pgconfig.org/#/tuning" target="_blank" rel="noopener noreferrer">PGConfig 2.0</a
    >
  </li>
  <li>
    <a href="http://pgconfigurator.cybertec.at/" target="_blank" rel="noopener noreferrer">Cybertec Postgres Configurator</a
    >
  </li>
</ul>
<p>
  운영체제의 종류, 메모리 크기 등을 선택해서 나온 설정값을 종합적으로 고려하여
  /etc/postgresql/9.6/main/postgresql.conf 파일을 수정하고 PostgreSQL을 다시
  시작한다. 내가 설정한 내용은 다음과 같다.
</p>
<pre class="language-none">
<code>shared_buffers = 1GB
work_mem = 64MB
maintenance_work_mem = 256MB
effective_io_concurrency = 2
wal_buffers = 16MB
max_wal_size = 2GB
min_wal_size = 512MB
checkpoint_completion_target = 0.7
random_page_cost = 4
effective_cache_size = 3GB
default_statistics_target = 100</code>
</pre>

<h5>관련 글</h5>
<ul>
  <li>
    <a href="https://www.bitneer.dev/wp/postgresql%ec%9d%98-%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%ec%99%80-%ec%82%ac%ec%9a%a9%ec%9e%90-%ec%83%9d%ec%84%b1-%eb%b0%b1%ec%97%85-%eb%b0%8f-%eb%b3%b5%ea%b5%ac/">PostgreSQL의 데이터베이스와 사용자 생성, 백업 및 복구</a
    >
  </li>
</ul>
<h5>참고 자료</h5>
<ul>
  <li>
    <a href="https://wiki.debian.org/PostgreSql" target="_blank" rel="noopener noreferrer">PostgreSql &#8211; Debian Wiki</a
    >
  </li>
  <li>
    <a href="https://www.postgresql.org/docs/manuals/" target="_blank" rel="noopener noreferrer">PostgreSQL: Manuals</a
    >
  </li>
  <li>
    <a href="https://www.postgresql.org/docs/11/libpq-pgpass.html" target="_blank" rel="noopener noreferrer">PostgreSQL: Documentation: 11: 34.15. The Password File</a
    >
  </li>
  <li>
    <a href="https://www.pgadmin.org/" target="_blank" rel="noopener noreferrer">pgAdmin PostgreSQL Tools</a
    >
  </li>
  <li>
    <a href="https://www.jetbrains.com/ko-kr/datagrip/features/" target="_blank" rel="noopener noreferrer">기능 및 스크린샷 &#8211; DataGrip</a
    >
  </li>
</ul><p>The post <a rel="nofollow" href="https://www.bitneer.dev/blog/%eb%8d%b0%eb%b9%84%ec%95%88%ec%9d%98-postgresql-%ec%84%a4%ec%b9%98%ec%99%80-%ec%84%a4%ec%a0%95/">데비안의 PostgreSQL 설치와 설정</a> appeared first on <a rel="nofollow" href="https://www.bitneer.dev">bitneer.dev</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
