~mysqlatfacebook/mysqlatfacebook/tools

« back to all changes in this revision

Viewing changes to prefetch/mysql.py

  • Committer: Domas Mituzas
  • Date: 2011-12-03 19:55:54 UTC
  • Revision ID: domas@facebook.com-20111203195554-xvvgeq6gw01cs4yq
Replication prefetcher:
* binlog.py - binlog reading class
* readahead.py - main chassis for replication event prefetching
* mysql.py - helper MySQL class
* rewriters.py - helper query 'rewrite' routines
* custom_query_prefetch.py - example for query-specific prefetcher
* fake_updates_prefetch.py - InnoDB fake changes based prefetcher

Licensed under Apache License 2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#
 
3
#   Copyright 2011 Facebook
 
4
#
 
5
#   Licensed under the Apache License, Version 2.0 (the "License");
 
6
#   you may not use this file except in compliance with the License.
 
7
#   You may obtain a copy of the License at
 
8
#
 
9
#       http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
#   Unless required by applicable law or agreed to in writing, software
 
12
#   distributed under the License is distributed on an "AS IS" BASIS,
 
13
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
#   See the License for the specific language governing permissions and
 
15
#   limitations under the License.
 
16
#
 
17
 
 
18
 
 
19
import time
 
20
import sys
 
21
import config
 
22
import _mysql
 
23
import MySQLdb
 
24
import MySQLdb.constants.CLIENT as CL
 
25
 
 
26
Error = MySQLdb.DatabaseError
 
27
 
 
28
class MySQL:
 
29
    _conn = None
 
30
 
 
31
    def __init__(self, init_connect=None):
 
32
        self.init_connect = init_connect
 
33
 
 
34
    """ Basic MySQL connection functionality """
 
35
    def reconnect(self):
 
36
        self._conn = None
 
37
 
 
38
        while self._conn == None:
 
39
            try:
 
40
                self._conn = _mysql.connect(
 
41
                    user=config.username,
 
42
                    passwd=config.password,
 
43
                    port=config.port,
 
44
                    host=config.host,
 
45
                    init_command="SET SESSION wait_timeout=5",
 
46
                    client_flag=CL.MULTI_STATEMENTS | CL.MULTI_RESULTS
 
47
                )
 
48
                if self.init_connect:
 
49
                    self.q(self.init_connect)
 
50
            except MemoryError:
 
51
                print sys.exc_info()
 
52
                sys.exit(1)
 
53
            except MySQLdb.Error:
 
54
                print sys.exc_info()
 
55
                time.sleep(1)
 
56
 
 
57
    def q(self, query, use_result=True):
 
58
        # Establish connection if not existing or fails to ping
 
59
        if not self._conn:
 
60
            self.reconnect()
 
61
 
 
62
        # We will retry just once - reconnect has infinite loop though
 
63
        for attempt in (True, False):
 
64
            try:
 
65
                self._conn.query(query)
 
66
                break  # if successful
 
67
            except MySQLdb.OperationalError:
 
68
                if attempt:
 
69
                    self.reconnect()
 
70
                    continue
 
71
                else:
 
72
                    return None
 
73
 
 
74
        if use_result:
 
75
            ret = []
 
76
            while True:
 
77
                r = self._conn.store_result()
 
78
                if not r:
 
79
                    # Certain statement sequences will
 
80
                    # produce multiple NULL resultsets,
 
81
                    # so we have to handle these properly
 
82
                    # ^^ - this is not a Haiku
 
83
                    if self._conn.next_result() < 0:
 
84
                        break
 
85
                    else:
 
86
                        continue
 
87
 
 
88
                while True:
 
89
                    row = r.fetch_row(how=1)
 
90
                    if row:
 
91
                        ret.append(row[0])
 
92
                    else:
 
93
                        break
 
94
 
 
95
            return ret
 
96
        else:
 
97
            return
 
98
 
 
99
if __name__ == "__main__":
 
100
    print MySQL().q("SELECT 'everything'; SET @a=1; "
 
101
                    "SELECT 1 FROM dual WHERE NULL; SELECT 'is'; SELECT 'ok'")