Unwinding shortened URLs with Python, SQLite, and multithreading
__

There is liitle need for the __. A single _ should suffice to make people clear it's a private attribute. If they really want to use it, __ won't stop the access

Linelength

Especially the lines with queries are too long. Can't you make those queries multiline?

From:

def updateUnwoundUrl(self, url_starting, url_unwound):
    self.__cursor.execute(
        'UPDATE url SET url_unwound = ? WHERE url_starting = ?', (url_unwound, url_starting))
    self.__conn.commit()
    return self.__cursor


to:

def updateUnwoundUrl(self, url_starting, url_unwound):
    self.__cursor.execute(
        '''UPDATE url 
           SET url_unwound = ? 
           WHERE url_starting = ?
        '''
        , (url_unwound, url_starting)
    )
    self.__conn.commit()
    return self.__cursor


Hoist the IO

If ever you want to change the db format to something else, you will need to change the internals of the code and how the my_db_path is made. 

To change this, I would follow the tips from this talk.

Database path

def unwindUrls(workers=100, request_timeout=10):
    relative_path = os.path.dirname(__file__)
    my_db_path = os.path.join(relative_path, 'database', 'my.db')


First, I would use my_db_path to handle filepaths.

Secondly I would add relative_path as an an argument, with Path('.') as default argument, this way you can specify the path.

def unwindUrls(workers=100, request_timeout=10):
    relative_path = os.path.dirname(__file__)
    my_db_path = os.path.join(relative_path, 'database', 'my.db')
    with MyDatabase(my_db_path) as my_db:

...
if __name__ == '__main__':
    unwindUrls()


To:

def unwindUrls(my_db, workers=100, request_timeout=10):

...
if __name__ == '__main__':
    my_db_path = pathlib.Path('.') / 'database' / 'my.db'
    with MyDatabase(my_db_path) as my_db:
        unwindUrls(my_db)


chunk_iter

def chunk_iter(iterable, chunk_size):
    it = iter(iterable)
    while True:
        chunk = tuple(next(it) for _ in range(chunk_size))
        if not chunk:
            break
        yield chunk


raises a Warning in Python 3.6


  C:\miniconda3\envs\test_env\lib\site-packages\ipykernel_launcher.py:4:
  DeprecationWarning: generator 'chunk_iter..' raised
  StopIteration   after removing the cwd from sys.path.


Better to use itertools.islice

def chunk_iter(iterable, chunk_size):
    it = iter(iterable)
    while True:
        chunk = tuple(islice(it, chunk_size))
        if not chunk:
            return
        yield chunk


Exception

a few time you use except Exception. This is way too broad. You should specify which Exceptions you want to catch