Skip to content

Commit ae966c2

Browse files
author
Jamie Isaacs
committed
Adding DBUtil dependency for mysqld monitoring.
1 parent 75a8267 commit ae966c2

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed

mysqld/python_modules/DBUtil.py

+218
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
"""
2+
The MIT License
3+
4+
Copyright (c) 2008 Gilad Raphaelli <gilad@raphaelli.com>
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
THE SOFTWARE.
23+
24+
if using < python2.5, http://code.activestate.com/recipes/523034/ works as a
25+
pure python collections.defaultdict substitute
26+
"""
27+
28+
#from collections import defaultdict
29+
try:
30+
from collections import defaultdict
31+
except:
32+
class defaultdict(dict):
33+
def __init__(self, default_factory=None, *a, **kw):
34+
if (default_factory is not None and
35+
not hasattr(default_factory, '__call__')):
36+
raise TypeError('first argument must be callable')
37+
dict.__init__(self, *a, **kw)
38+
self.default_factory = default_factory
39+
def __getitem__(self, key):
40+
try:
41+
return dict.__getitem__(self, key)
42+
except KeyError:
43+
return self.__missing__(key)
44+
def __missing__(self, key):
45+
if self.default_factory is None:
46+
raise KeyError(key)
47+
self[key] = value = self.default_factory()
48+
return value
49+
def __reduce__(self):
50+
if self.default_factory is None:
51+
args = tuple()
52+
else:
53+
args = self.default_factory,
54+
return type(self), args, None, None, self.items()
55+
def copy(self):
56+
return self.__copy__()
57+
def __copy__(self):
58+
return type(self)(self.default_factory, self)
59+
def __deepcopy__(self, memo):
60+
import copy
61+
return type(self)(self.default_factory,
62+
copy.deepcopy(self.items()))
63+
def __repr__(self):
64+
return 'defaultdict(%s, %s)' % (self.default_factory,
65+
dict.__repr__(self))
66+
67+
import MySQLdb
68+
69+
def longish(x):
70+
if len(x):
71+
try:
72+
return long(x)
73+
except ValueError:
74+
return longish(x[:-1])
75+
else:
76+
raise ValueError
77+
78+
def parse_innodb_status(innodb_status_raw):
79+
def sumof(status):
80+
def new(*idxs):
81+
return sum(map(lambda x: longish(status[x]), idxs))
82+
#new.func_name = 'sumof' #not ok in py2.3
83+
return new
84+
85+
innodb_status = defaultdict(int)
86+
innodb_status['active_transactions']
87+
88+
for line in innodb_status_raw:
89+
istatus = line.split()
90+
91+
isum = sumof(istatus)
92+
93+
# SEMAPHORES
94+
if "Mutex spin waits" in line:
95+
innodb_status['spin_waits'] += longish(istatus[3])
96+
innodb_status['spin_rounds'] += longish(istatus[5])
97+
innodb_status['os_waits'] += longish(istatus[8])
98+
99+
elif "RW-shared spins" in line:
100+
innodb_status['spin_waits'] += isum(2,8)
101+
innodb_status['os_waits'] += isum(5,11)
102+
103+
# TRANSACTIONS
104+
elif "Trx id counter" in line:
105+
innodb_status['transactions'] += isum(3,4)
106+
107+
elif "Purge done for trx" in line:
108+
innodb_status['transactions_purged'] += isum(6,7)
109+
110+
elif "History list length" in line:
111+
innodb_status['history_list'] = longish(istatus[3])
112+
113+
elif "---TRANSACTION" in line and innodb_status['transactions']:
114+
innodb_status['current_transactions'] += 1
115+
if "ACTIVE" in line:
116+
innodb_status['active_transactions'] += 1
117+
118+
elif "LOCK WAIT" in line and innodb_status['transactions']:
119+
innodb_status['locked_transactions'] += 1
120+
121+
elif 'read views open inside' in line:
122+
innodb_status['read_views'] = longish(istatus[0])
123+
124+
# FILE I/O
125+
elif 'OS file reads' in line:
126+
innodb_status['data_reads'] = longish(istatus[0])
127+
innodb_status['data_writes'] = longish(istatus[4])
128+
innodb_status['data_fsyncs'] = longish(istatus[8])
129+
130+
elif 'Pending normal aio' in line:
131+
innodb_status['pending_normal_aio_reads'] = longish(istatus[4])
132+
innodb_status['pending_normal_aio_writes'] = longish(istatus[7])
133+
134+
elif 'ibuf aio reads' in line:
135+
innodb_status['pending_ibuf_aio_reads'] = longish(istatus[3])
136+
innodb_status['pending_aio_log_ios'] = longish(istatus[6])
137+
innodb_status['pending_aio_sync_ios'] = longish(istatus[9])
138+
139+
elif 'Pending flushes (fsync)' in line:
140+
innodb_status['pending_log_flushes'] = longish(istatus[4])
141+
innodb_status['pending_buffer_pool_flushes'] = longish(istatus[7])
142+
143+
# INSERT BUFFER AND ADAPTIVE HASH INDEX
144+
elif 'merged recs' in line:
145+
innodb_status['ibuf_inserts'] = longish(istatus[0])
146+
innodb_status['ibuf_merged'] = longish(istatus[2])
147+
innodb_status['ibuf_merges'] = longish(istatus[5])
148+
149+
# LOG
150+
elif "log i/o's done" in line:
151+
innodb_status['log_writes'] = longish(istatus[0])
152+
153+
elif "pending log writes" in line:
154+
innodb_status['pending_log_writes'] = longish(istatus[0])
155+
innodb_status['pending_chkp_writes'] = longish(istatus[4])
156+
157+
elif "Log sequence number" in line:
158+
innodb_status['log_bytes_written'] = isum(3,4)
159+
160+
elif "Log flushed up to" in line:
161+
innodb_status['log_bytes_flushed'] = isum(4,5)
162+
163+
# BUFFER POOL AND MEMORY
164+
elif "Buffer pool size" in line:
165+
innodb_status['buffer_pool_pages_total'] = longish(istatus[3])
166+
167+
elif "Free buffers" in line:
168+
innodb_status['buffer_pool_pages_free'] = longish(istatus[2])
169+
170+
elif "Database pages" in line:
171+
innodb_status['buffer_pool_pages_data'] = longish(istatus[2])
172+
173+
elif "Modified db pages" in line:
174+
innodb_status['buffer_pool_pages_dirty'] = longish(istatus[3])
175+
176+
elif "Pages read" in line:
177+
innodb_status['pages_read'] = longish(istatus[2])
178+
innodb_status['pages_created'] = longish(istatus[4])
179+
innodb_status['pages_written'] = longish(istatus[6])
180+
181+
# ROW OPERATIONS
182+
elif 'Number of rows inserted' in line:
183+
innodb_status['rows_inserted'] = longish(istatus[4])
184+
innodb_status['rows_updated'] = longish(istatus[6])
185+
innodb_status['rows_deleted'] = longish(istatus[8])
186+
innodb_status['rows_read'] = longish(istatus[10])
187+
188+
elif "queries inside InnoDB" in line:
189+
innodb_status['queries_inside'] = longish(istatus[0])
190+
innodb_status['queries_queued'] = longish(istatus[4])
191+
192+
# Some more stats
193+
innodb_status['transactions_unpurged'] = innodb_status['transactions'] - innodb_status['transactions_purged']
194+
innodb_status['log_bytes_unflushed'] = innodb_status['log_bytes_written'] - innodb_status['log_bytes_flushed']
195+
196+
return innodb_status
197+
198+
if __name__ == '__main__':
199+
from optparse import OptionParser
200+
201+
parser = OptionParser()
202+
parser.add_option("-H", "--Host", dest="host", help="Host running mysql", default="localhost")
203+
parser.add_option("-u", "--user", dest="user", help="user to connect as", default="")
204+
parser.add_option("-p", "--password", dest="passwd", help="password", default="")
205+
(options, args) = parser.parse_args()
206+
207+
try:
208+
conn = MySQLdb.connect(user=options.user, host=options.host, passwd=options.passwd)
209+
210+
cursor = conn.cursor(MySQLdb.cursors.Cursor)
211+
cursor.execute("SHOW /*!50000 ENGINE*/ INNODB STATUS")
212+
innodb_status = parse_innodb_status(cursor.fetchone()[0].split('\n'))
213+
cursor.close()
214+
215+
conn.close()
216+
except MySQLdb.OperationalError, (errno, errmsg):
217+
raise
218+

0 commit comments

Comments
 (0)