Commit 431a092d 431a092dd9113690f2a6fbbea04a4f5b526e8150 by Christian Gerdes

First version with PDB support in LILOM. Needs more testing.

1 parent e8332d60
No preview for this file type
1 # Notes
2
3 ## PDB logic
4
5 Bytt approuch och tagit bort allt som tidigare fanns i PDB branchen och har mergat den med master (då den innehöll TNS koden).
6
7 Gamla tanken var att via en PDB klura ut vad CDB databasens conn sträng är, ansluta till den, och hämta data för alla PDBer istället och cacha detta i CDB objektet.
8 Hade funkat fint, förutom att det förutsätter att CDB och PDB har samma lyssnare, vilket de inte nödvändigtvist har. Jag kan inte klura ut vad lyssnaren ska vara till CDB.
9
10 Istället får det bli en lösning där användaren alltid anger CDB databasens conn sträng, men kan med en flagga välja att få ut en PDB's info istället.
11
12 Idag ser tex ett anrop ut så här:
13
14 GET /OraMonREST/getData?age=14&connectionString=jdbc%3Aoracle%3Athin%3A%40%2F%2Fu03634.kap.rsv.se%3A1526%2FDB1K12
15
16 I detta kan vi lägga till en parameter, forPDB=DA1K001 tex och då returneras endast värden för den PDB'n.
17 På så sätt kommer anrop till flera olika PDB att hämtas från samma CDB data cache.
18 Anropet till CDB'n skulle kunna returnera en lista på alla PDBer också.
19 Ännu snyggare vore om en CDB kunde bryta ner graferna per PDB också ;)
20
21 SQL satser
22
23 select cdb from v$database;
24 Returnerar YES om databasen är en CDB (dvs Oracle 12 med CDB påslaget). Returnerar YES även på en PDB.
25
26 Views for PDB's
27
28 V_$CON_SYSSTAT
29 V_$CON_SYSTEM_WAIT_CLASS
30 V_$CON_SYSTEM_EVENT
31 V_$CON_SYS_TIME_MODEL
32
33 Can be checked with a select like
34 select view_name from all_views where view_name like 'V_$CON_%';
35
36 Slå samman con_id med statname
37 select systimestamp, name || con_id, value from V$CON_SYSSTAT;
38
39 2018-03-28
40 Första versionen med PDB stöd. Behövs mer tester.
41
42 PDB CPU: 11.056953715796771
43 CDB CPU: 11.204673034978592
44 DA1K001: 11.084891829252536
45 DA1K002: 55.75905904774211
46 TOTAL : 66.84395087699465
47
48 Exemplet ovan är med ett delta på 60 sekunder, PDB går direkt mot PDB con string, CDB direkt mot CDB och DA räknarna är från denna CDB.
49 DA1K002 är på samma CDB, och getCPUPercent() ovan returnerar av någon anledning att den tar 55% cpu när hela CDB bara tar 11.2 vilket känns fel.
50 Det är bara DA1K001 som jobbar. Nedan från samma mätning fast Logical IO per Second istället:
51
52 PDB LIO: 433961.7046663872
53 CDB LIO: 433532.02901594585
54 DA1K001: 435343.22211814864
55 DA1K002: 9.075934239850135
56 TOTAL : 435352.2980523885
57
58 Här känns alla värden rätt.
...\ No newline at end of file ...\ No newline at end of file
...@@ -83,4 +83,17 @@ class Collector { ...@@ -83,4 +83,17 @@ class Collector {
83 else 83 else
84 return 0; 84 return 0;
85 } 85 }
86
87 public double getSeconds(String name) throws Throwable {
88 LongDelta myDelta = null;
89 for(int x = 0; x<list.size() && myDelta == null; x++) {
90 if(name.equals(list.get(x).name)) {
91 myDelta = list.get(x);
92 }
93 }
94 if(myDelta != null)
95 return myDelta.getSeconds();
96 else
97 return 0;
98 }
86 } 99 }
...\ No newline at end of file ...\ No newline at end of file
......
1 package se.lil.om; 1 package se.lil.om;
2 2
3 import java.sql.*; 3 import java.sql.*;
4 import java.util.ArrayList;
5 import java.util.HashMap;
4 import java.util.Properties; 6 import java.util.Properties;
5 import java.util.concurrent.locks.Lock; 7 import java.util.concurrent.locks.Lock;
6 import java.util.concurrent.locks.ReentrantLock; 8 import java.util.concurrent.locks.ReentrantLock;
...@@ -15,11 +17,6 @@ public class OraMon { ...@@ -15,11 +17,6 @@ public class OraMon {
15 String dbName = null; 17 String dbName = null;
16 String serviceName = null; 18 String serviceName = null;
17 19
18 Boolean isPDB = false;
19 Boolean isCDB = false;
20 Boolean hasContainers = null;
21 OraMon containerDB = null;
22
23 public static final int SYSSTAT = 1; 20 public static final int SYSSTAT = 1;
24 public static final int OSSTAT = 2; 21 public static final int OSSTAT = 2;
25 22
...@@ -29,6 +26,13 @@ public class OraMon { ...@@ -29,6 +26,13 @@ public class OraMon {
29 int getDataCalls = 0; 26 int getDataCalls = 0;
30 int getDataSucess = 0; 27 int getDataSucess = 0;
31 28
29 boolean getPdbs = false;
30 Collector colPdbSysStat = null;
31 Collector colPdbCPU = null;
32 public static final String strCpuTime = " cputime";
33 public static final String strNiwTime = " niwtime";
34 public static final String strSeparator = " ";
35
32 public int getDataCalled() { 36 public int getDataCalled() {
33 return getDataCalls; 37 return getDataCalls;
34 } 38 }
...@@ -81,48 +85,80 @@ public class OraMon { ...@@ -81,48 +85,80 @@ public class OraMon {
81 //DB CPU 85 //DB CPU
82 LongDelta cpuTime = new LongDelta(true); 86 LongDelta cpuTime = new LongDelta(true);
83 LongDelta niwTime = new LongDelta(true); 87 LongDelta niwTime = new LongDelta(true);
84 public double getCPUPercent(boolean excludeNonIdleWaitTime) throws Throwable { 88 public double getCPUPercent(boolean excludeNonIdleWaitTime, String pdbName) throws Throwable {
85 double perSec = cpuTime.getPerSecondValue(); 89 double cpuPerSec;
90 if(pdbName == null) cpuPerSec = cpuTime.getPerSecondValue();
91 else cpuPerSec = colPdbCPU.getPerSecValue(pdbName + strCpuTime);
92
93 double niwPerSec;
94 if(pdbName == null) niwPerSec = niwTime.getPerSecondValue();
95 else niwPerSec = colPdbCPU.getPerSecValue(pdbName + strNiwTime);
96
86 if(excludeNonIdleWaitTime) { 97 if(excludeNonIdleWaitTime) {
87 double newPerSec = perSec - (niwTime.getPerSecondValue() * 1000); 98 double newPerSec = cpuPerSec - (niwPerSec * 1000);
88 if(newPerSec > 0) perSec = newPerSec; else perSec = 0; 99 if(newPerSec > 0) cpuPerSec = newPerSec; else cpuPerSec = 0;
89 } 100 }
90 double totSec = numCpus * 1000 * 1000; 101 double totSec = numCpus * 1000 * 1000;
91 double percent = (perSec / totSec) * 100; 102 double percent = (cpuPerSec / totSec) * 100;
92 if(percent > 100D) percent=100D; 103 if(percent > 100D) percent=100D;
93 if(percent < 0D) percent=0D; 104 if(percent < 0D) percent=0D;
94 return percent; 105 return percent;
95 } 106 }
107 public double getCPUPercent(boolean excludeNonIdleWaitTime) throws Throwable {
108 return getCPUPercent(excludeNonIdleWaitTime, null);
109 }
96 public double getCPUPercent() throws Throwable { 110 public double getCPUPercent() throws Throwable {
97 return getCPUPercent(false); 111 return getCPUPercent(false);
98 } 112 }
113 public double getCPUPercent(String pdbName) throws Throwable {
114 return getCPUPercent(false, pdbName);
115 }
116
99 public double getCPUAvailableSeconds() throws Throwable { 117 public double getCPUAvailableSeconds() throws Throwable {
100 return cpuTime.getSeconds()*numCpus; 118 return cpuTime.getSeconds()*numCpus;
101 } 119 }
120 public double getCPUAvailableSeconds(String pdbName) throws Throwable {
121 return colPdbCPU.getSeconds(pdbName + strCpuTime)*numCpus;
122 }
123
102 public long getCPURawValue() throws Throwable { 124 public long getCPURawValue() throws Throwable {
103 return cpuTime.getCurrentValue(); 125 return cpuTime.getCurrentValue();
104 } 126 }
105 public long getCPURawDiff() { 127 public long getCPURawValue(String pdbName) throws Throwable {
106 if(cpuTime != null && cpuTime.lastValue != null) 128 return colPdbCPU.getCurrentValue(pdbName + strCpuTime);
107 return cpuTime.curValue - cpuTime.lastValue; 129 }
108 else 130
109 return 0; 131 public long getCPURawDiff() throws Throwable {
132 return cpuTime.getDelta();
133 }
134 public long getCPURawDiff(String pdbName) throws Throwable {
135 return colPdbCPU.getDelta(pdbName + strCpuTime);
110 } 136 }
111 137
112 public double getCPUTimePerSecond() throws Throwable { 138 public double getCPUTimePerSecond() throws Throwable {
113 return cpuTime.getPerSecondValue(); 139 return cpuTime.getPerSecondValue();
114 } 140 }
141 public double getCPUTimePerSecond(String pdbName) throws Throwable {
142 return colPdbCPU.getPerSecValue(pdbName + strCpuTime);
143 }
115 144
116 public double getPerSecondValue(String name) throws Throwable { 145 public double getPerSecondValue(String name) throws Throwable {
117 return getPerSecondValue(name, SYSSTAT); 146 return getPerSecondValue(name, SYSSTAT, null);
118 } 147 }
119 148
120 public double getPerSecondValue(String name, int table) throws Throwable { 149 public double getPerSecondValue(String name, int table) throws Throwable {
150 return getPerSecondValue(name, table, null);
151 }
152
153 public double getPerSecondValue(String name, int table, String pdbName) throws Throwable {
121 switch (table) { 154 switch (table) {
122 case OSSTAT: 155 case OSSTAT:
123 return colOsStat.getPerSecValue(name); 156 return colOsStat.getPerSecValue(name);
124 case SYSSTAT: 157 case SYSSTAT:
158 if(pdbName == null)
125 return colSysStat.getPerSecValue(name); 159 return colSysStat.getPerSecValue(name);
160 else
161 return colPdbSysStat.getPerSecValue(pdbName + strSeparator + name);
126 default: 162 default:
127 return colSysStat.getPerSecValue(name); 163 return colSysStat.getPerSecValue(name);
128 } 164 }
...@@ -140,10 +176,6 @@ public class OraMon { ...@@ -140,10 +176,6 @@ public class OraMon {
140 else return this.dbName; 176 else return this.dbName;
141 } 177 }
142 178
143 public boolean isPDB() {
144 return isPDB;
145 }
146
147 public double getOsBusyPercent() throws Throwable { 179 public double getOsBusyPercent() throws Throwable {
148 double idle = getPerSecondValue("IDLE_TIME", OSSTAT); 180 double idle = getPerSecondValue("IDLE_TIME", OSSTAT);
149 double busy = getPerSecondValue("BUSY_TIME", OSSTAT); 181 double busy = getPerSecondValue("BUSY_TIME", OSSTAT);
...@@ -171,9 +203,23 @@ public class OraMon { ...@@ -171,9 +203,23 @@ public class OraMon {
171 } 203 }
172 204
173 public double getBufferCacheHitRatioPercent() throws Throwable { 205 public double getBufferCacheHitRatioPercent() throws Throwable {
174 double conGetsCache = getPerSecondValue("consistent gets from cache"); 206 return getBufferCacheHitRatioPercent(null);
175 double dbBlocksCache = getPerSecondValue("db block gets from cache"); 207 }
176 double physReadsCache = getPerSecondValue("physical reads cache"); 208 public double getBufferCacheHitRatioPercent(String pdbName) throws Throwable {
209 double conGetsCache;
210 double dbBlocksCache;
211 double physReadsCache;
212
213 if(pdbName == null) {
214 conGetsCache = getPerSecondValue("consistent gets from cache");
215 dbBlocksCache = getPerSecondValue("db block gets from cache");
216 physReadsCache = getPerSecondValue("physical reads cache");
217 } else {
218 conGetsCache = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "consistent gets from cache");
219 dbBlocksCache = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "db block gets from cache");
220 physReadsCache = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "physical reads cache");
221 }
222
177 if (conGetsCache + dbBlocksCache + physReadsCache == 0) { 223 if (conGetsCache + dbBlocksCache + physReadsCache == 0) {
178 return 100; 224 return 100;
179 } 225 }
...@@ -189,9 +235,23 @@ public class OraMon { ...@@ -189,9 +235,23 @@ public class OraMon {
189 } 235 }
190 236
191 public double getCacheHitRatioPercent() throws Throwable { 237 public double getCacheHitRatioPercent() throws Throwable {
192 double conGets = getPerSecondValue("consistent gets"); 238 return getCacheHitRatioPercent(null);
193 double dbBlocks = getPerSecondValue("db block gets"); 239 }
194 double physReads = getPerSecondValue("physical reads"); 240 public double getCacheHitRatioPercent(String pdbName) throws Throwable {
241 double conGets;
242 double dbBlocks;
243 double physReads;
244
245 if(pdbName == null) {
246 conGets = getPerSecondValue("consistent gets");
247 dbBlocks = getPerSecondValue("db block gets");
248 physReads = getPerSecondValue("physical reads");
249 } else {
250 conGets = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "consistent gets");
251 dbBlocks = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "db block gets");
252 physReads = colPdbSysStat.getPerSecValue(pdbName + strSeparator + "physical reads");
253 }
254
195 if (conGets + dbBlocks + physReads == 0) { 255 if (conGets + dbBlocks + physReads == 0) {
196 return 100; 256 return 100;
197 } 257 }
...@@ -206,7 +266,13 @@ public class OraMon { ...@@ -206,7 +266,13 @@ public class OraMon {
206 } 266 }
207 267
208 public double getLogicalReadsPerSecond() throws Throwable { 268 public double getLogicalReadsPerSecond() throws Throwable {
269 return getLogicalReadsPerSecond(null);
270 }
271 public double getLogicalReadsPerSecond(String pdbName) throws Throwable {
272 if(pdbName == null)
209 return getPerSecondValue("consistent gets") + getPerSecondValue("db block gets"); 273 return getPerSecondValue("consistent gets") + getPerSecondValue("db block gets");
274 else
275 return colPdbSysStat.getPerSecValue(pdbName + strSeparator + "consistent gets") + colPdbSysStat.getPerSecValue(pdbName + strSeparator + "db block gets");
210 } 276 }
211 277
212 long lastRTns = 0; 278 long lastRTns = 0;
...@@ -221,15 +287,24 @@ public class OraMon { ...@@ -221,15 +287,24 @@ public class OraMon {
221 } 287 }
222 288
223 public boolean getData() throws Throwable { 289 public boolean getData() throws Throwable {
224 return getData(0); 290 return getData(0, null);
291 }
292
293 public boolean getData(long ageTs) throws Throwable {
294 return getData(ageTs, null);
225 } 295 }
226 296
227 Lock lock = new ReentrantLock(); 297 Lock lock = new ReentrantLock();
228 Throwable lastEx = null; 298 Throwable lastEx = null;
229 299
230 public boolean getData(long ageTs) throws Throwable { 300 public boolean getData(long ageTs, String pdbName) throws Throwable {
231 //Check age 301 //Check age (unless pdbName was set for the first time, in that case we need to discard the cached data)
302 if(getPdbs == false && pdbName != null) {
303 getPdbs = true;
304 }
305 else {
232 if ((System.nanoTime() - lastFetchTSns) < (ageTs * 1000 * 1000 * 1000)) return false; 306 if ((System.nanoTime() - lastFetchTSns) < (ageTs * 1000 * 1000 * 1000)) return false;
307 }
233 308
234 // Start thread safe 309 // Start thread safe
235 // Try to get a lock 310 // Try to get a lock
...@@ -283,8 +358,6 @@ public class OraMon { ...@@ -283,8 +358,6 @@ public class OraMon {
283 // Get OS Load 358 // Get OS Load
284 osLoad.update(stmt.executeQuery("select systimestamp, value from V$OSSTAT where stat_name='LOAD'")); 359 osLoad.update(stmt.executeQuery("select systimestamp, value from V$OSSTAT where stat_name='LOAD'"));
285 360
286 // SYSSTAT and SYS_TIME_MODEL are specific for PDB and CDB/Instance is the total.
287
288 // Get DB CPU use time 361 // Get DB CPU use time
289 rset = stmt.executeQuery("select systimestamp, s.value as NIWT, t.value as DBCPU from V$SYSSTAT s, V$SYS_TIME_MODEL t where s.name='non-idle wait time' and t.STAT_NAME='DB CPU'"); 362 rset = stmt.executeQuery("select systimestamp, s.value as NIWT, t.value as DBCPU from V$SYSSTAT s, V$SYS_TIME_MODEL t where s.name='non-idle wait time' and t.STAT_NAME='DB CPU'");
290 rset.next(); 363 rset.next();
...@@ -295,6 +368,22 @@ public class OraMon { ...@@ -295,6 +368,22 @@ public class OraMon {
295 //Get the entire V_$SYSSTAT table from DB 368 //Get the entire V_$SYSSTAT table from DB
296 colSysStat.update(stmt.executeQuery("select systimestamp, name, value from V$SYSSTAT")); 369 colSysStat.update(stmt.executeQuery("select systimestamp, name, value from V$SYSSTAT"));
297 370
371 //Get PDB specific data if getPDB is set to true
372 if(getPdbs) {
373 //CPU
374 if(colPdbCPU == null) colPdbCPU = new Collector();
375 rset = stmt.executeQuery("select systimestamp, c.NAME, s.value as NIWT, t.value as DBCPU from V$CON_SYSSTAT s, V$CON_SYS_TIME_MODEL t, V$CONTAINERS c where s.CON_ID=t.CON_ID and s.CON_ID=c.CON_ID and s.name='non-idle wait time' and t.STAT_NAME='DB CPU'");
376 while(rset.next()) {
377 colPdbCPU.updateValue(rset.getTimestamp(1), rset.getString(2) + strNiwTime, rset.getLong(3));
378 colPdbCPU.updateValue(rset.getTimestamp(1), rset.getString(2) + strCpuTime, rset.getLong(4));
379 }
380 rset.close();
381
382 //SYSSTATS
383 if(colPdbSysStat == null) colPdbSysStat = new Collector();
384 colPdbSysStat.update(stmt.executeQuery("select systimestamp, c.NAME || '" + strSeparator + "' || s.name, s.value from V$CON_SYSSTAT s, V$CONTAINERS c where s.CON_ID=c.CON_ID"));
385 }
386
298 stmt.close(); 387 stmt.close();
299 getDataSucess++; 388 getDataSucess++;
300 lastFetchTSns = System.nanoTime(); 389 lastFetchTSns = System.nanoTime();
......
...@@ -14,7 +14,36 @@ public class TestRunner { ...@@ -14,7 +14,36 @@ public class TestRunner {
14 public static void main(String[] args) throws Throwable { 14 public static void main(String[] args) throws Throwable {
15 //runner1(); 15 //runner1();
16 //test1(); 16 //test1();
17 testTns(); 17 //testTns();
18 testPDB();
19 }
20
21 public static void testPDB() throws Throwable {
22 OraMon cdb = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DB1K12","dbsnmp","dbsnmp"); // CDB
23 OraMon pdb = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DA1K001","dbsnmp","dbsnmp"); // PDB
24
25 int times = 5;
26 while(times-- > 0) {
27 cdb.getData(0, "DA1K001");
28 pdb.getData();
29
30 System.out.println("PDB CPU: " + pdb.getCPUPercent());
31 System.out.println("CDB CPU: " + cdb.getCPUPercent());
32 System.out.println("DA1K001: " + cdb.getCPUPercent(false, "DA1K001"));
33 System.out.println("DA1K002: " + cdb.getCPUPercent(false, "DA1K002"));
34 System.out.println("TOTAL : " + (cdb.getCPUPercent(false, "DA1K001") + cdb.getCPUPercent(false, "DA1K002")));
35
36 System.out.println("PDB LIO: " + pdb.getLogicalReadsPerSecond());
37 System.out.println("CDB LIO: " + cdb.getLogicalReadsPerSecond());
38 System.out.println("DA1K001: " + cdb.getLogicalReadsPerSecond("DA1K001"));
39 System.out.println("DA1K002: " + cdb.getLogicalReadsPerSecond("DA1K002"));
40 System.out.println("TOTAL : " + (cdb.getLogicalReadsPerSecond("DA1K001") + cdb.getLogicalReadsPerSecond("DA1K002")));
41
42 System.out.println("Sleeping 15s\n");
43 Thread.sleep(60000);
44 }
45 cdb.close();
46 pdb.close();
18 } 47 }
19 48
20 public static void test1() throws Throwable { 49 public static void test1() throws Throwable {
...@@ -42,8 +71,9 @@ public class TestRunner { ...@@ -42,8 +71,9 @@ public class TestRunner {
42 71
43 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@uvp3dbkappkg:1550:VP1K03","dbsnmp","dbsnmp"); // SID eller Service Name format 72 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@uvp3dbkappkg:1550:VP1K03","dbsnmp","dbsnmp"); // SID eller Service Name format
44 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u00154.kap.rsv.se:1526/DB1K01","dbsnmp","dbsnmp"); 73 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u00154.kap.rsv.se:1526/DB1K01","dbsnmp","dbsnmp");
45 OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DA1K001","dbsnmp","dbsnmp"); // PDB, CDB är DB1K12 74 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DA1K001","dbsnmp","dbsnmp"); // PDB, CDB är DB1K12
46 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DA1K002","dbsnmp","dbsnmp"); // Andra PDB på CDB DB1K12 75 //OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DA1K002","dbsnmp","dbsnmp"); // Andra PDB på CDB DB1K12
76 OraMon mon1 = new OraMon("jdbc:oracle:thin:@//u03634.kap.rsv.se:1526/DB1K12","dbsnmp","dbsnmp"); // PDB, CDB är DB1K12
47 //OraMon mon2 = new OraMon("jdbc:oracle:thin:@host:port:sid","user","pass"); // SID format 77 //OraMon mon2 = new OraMon("jdbc:oracle:thin:@host:port:sid","user","pass"); // SID format
48 mon1.open(); 78 mon1.open();
49 //mon2.open(); 79 //mon2.open();
......