Index: django/contrib/sessions/tests.py
===================================================================
--- django/contrib/sessions/tests.py	(revision 10645)
+++ django/contrib/sessions/tests.py	(working copy)
@@ -33,7 +33,7 @@
 >>> prev_key = db_session.session_key
 >>> db_session.flush()
 >>> db_session.exists(prev_key)
-False
+True
 >>> db_session.session_key == prev_key
 False
 >>> db_session.modified, db_session.accessed
@@ -48,6 +48,10 @@
 >>> db_session.items() == prev_data
 True
 
+# Calling cycle_key when no session exists does not raise AttributeError.
+>>> db_session = DatabaseSession()
+>>> db_session.cycle_key()
+
 # Submitting an invalid session key (either by guessing, or if the db has
 # removed the key) results in a new key being generated.
 >>> Session.objects.filter(pk=db_session.session_key).delete()
@@ -110,7 +114,7 @@
 >>> prev_key = file_session.session_key
 >>> file_session.flush()
 >>> file_session.exists(prev_key)
-False
+True
 >>> file_session.session_key == prev_key
 False
 >>> file_session.modified, file_session.accessed
@@ -168,7 +172,7 @@
 >>> prev_key = cache_session.session_key
 >>> cache_session.flush()
 >>> cache_session.exists(prev_key)
-False
+True
 >>> cache_session.session_key == prev_key
 False
 >>> cache_session.modified, cache_session.accessed
@@ -383,6 +387,90 @@
 >>> settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = original_expire_at_browser_close
 """
 
+from django.test import TestCase
+from django.http import HttpRequest, HttpResponse
+from django.contrib.sessions.middleware import SessionMiddleware
+from django.conf import settings
+
+class SessionTest(TestCase):
+    def generic_view(self, request):
+        request.session["seen_this_user_before"] = 1
+        return HttpResponse("")
+
+    def cycle_view(self, request):
+        request.session.cycle_key()
+        request.session["login_key"] = 1
+        return HttpResponse("")
+
+    def flush_view(self, request):
+        request.session.flush()
+        request.session["login_key"] = 1
+        return HttpResponse("")
+
+    def ajax_view(self, request):
+        self.assertEqual(request.session.get("login_key", None), None)
+        return HttpResponse("")
+
+    def still_logged_in_view(self, request):
+        self.assertEqual(request.session.get("login_key"), 1)
+        return HttpResponse("")
+
+    @staticmethod
+    def run_view(view, client_cookies, session_cookie_override = None):
+        request_cookies = client_cookies.copy()
+        if session_cookie_override is not None:
+            request_cookies[settings.SESSION_COOKIE_NAME] = session_cookie_override
+
+        request = HttpRequest()
+        request.COOKIES = request_cookies
+
+        mid = SessionMiddleware()
+        mid.process_request(request)
+        response = view(request)
+        mid.process_response(request, response)
+
+        for cookie in response.cookies.itervalues():
+            client_cookies[cookie.key] = cookie.value
+        return response
+
+    def _test_session_race(self, flush):
+        # This test will fail if settings.SESSION_SAVE_EVERY_REQUEST is set.
+        if settings.SESSION_SAVE_EVERY_REQUEST:
+            return
+
+        # This dict simulates the cookie store on a user client.
+        cookies = {}
+
+        # The user logs in, and receives a session cookie for a login key.
+        # The user accesses the site, and receives a session cookie.
+        response = self.run_view(self.generic_view, cookies)
+        original_session_cookie = response.cookies.get(settings.SESSION_COOKIE_NAME, False)
+        self.assertNotEqual(original_session_cookie, False)
+
+        # The user logs into the site, triggering session.flush, and receives a new session cookie.
+        if flush:
+            response = self.run_view(self.flush_view, cookies)
+        else:
+            response = self.run_view(self.cycle_view, cookies)
+        new_session_cookie = response.cookies.get(settings.SESSION_COOKIE_NAME, False)
+        self.assertNotEqual(new_session_cookie, False)
+        self.assertNotEqual(new_session_cookie.value, original_session_cookie.value)
+
+        # A delayed AJAX request comes in using the original session.  The request should use
+        # the old session and not set a session.  The user is not logged in during this request.
+        response = self.run_view(self.ajax_view, cookies, original_session_cookie.value)
+        unset_session_cookie = response.cookies.get(settings.SESSION_COOKIE_NAME, False)
+        self.assertEqual(unset_session_cookie, False)
+
+        # The user should still be logged in.
+        response = self.run_view(self.still_logged_in_view, cookies)
+
+    def test_session_race_with_flush(self):
+        self._test_session_race(True)
+
+    def test_session_race_with_cycle(self):
+        self._test_session_race(False)
+
 if __name__ == '__main__':
     import doctest
     doctest.testmod()
Index: django/contrib/sessions/backends/base.py
===================================================================
--- django/contrib/sessions/backends/base.py	(revision 10645)
+++ django/contrib/sessions/backends/base.py	(working copy)
@@ -236,18 +236,15 @@
         key.
         """
         self.clear()
-        self.delete()
         self.create()
 
     def cycle_key(self):
         """
         Creates a new session key, whilst retaining the current session data.
         """
-        data = self._session_cache
-        key = self.session_key
-        self.create()
+        data = self._get_session()
+        self.flush()
         self._session_cache = data
-        self.delete(key)
 
     # Methods that child classes must implement.
 
